cancel
Showing results for 
Search instead for 
Did you mean: 

Dynamic Groups Automation Using The API

dwjohn
JumpCloud Employee
JumpCloud Employee

Introduction

Use the JumpCloud API to configure and update both static user and device groups to dynamic groups. Dynamic Groups are groups with attribute-driven rules that allow membership to be either fully automated, or require a review prior to the membership change taking place.

Instead of the Admin Portal, JumpCloud admins can use this article to build automated workflows in the API around user and device group membership. Resultingly, all applied entitlements will automatically take effect, with or without review, and update group memberships without having to manually change group membership.

Dynamic Groups: Attributes, Operators, and Values

User Groups

The following table shows which attributes, operators, and values are currently supported when configuring rules for a dynamic user group via memberQuery.

Several of the attributes' valid values are free text fields, meaning that you can input any text string. Currently, there is no validation for the values when setting a rule with one of these attributes. The value used for the rule must match exactly what has been entered for the user in order for it to be returned in the query. Any invalid operator or value used via memberQuery may return no result or an unexpected result.

 

Attribute

 

Operators

 

Valid Values

 

company

eq, ne, in

free text field

costCenter

eq, ne, in

free text field

description

eq, ne, in

free text field

department

eq, ne, in

free text field

employeeType

eq, ne, in

free text field

jobTitle

eq, ne, in

free text field

location

eq, ne, in

free text field

userState

eq, ne, in

active
staged
suspended

Device Groups

The following table shows which attributes, operators, and values are currently supported when configuring rules for a dynamic device group via memberQuery.

Note that there is currently no validation for operators or valid values. Any invalid operator or value used via memberQuery may return no result or unexpected result.

 

Attribute

 

Operators

 

Valid Values

 

osFamily

eq, ne, in

darwin (MacOS)
windows
linux
ios (iOS/iPadOS)
android

archFamily

eq, ne, in

amd64 (64-bit x86)
386 (32-bit x86)
arm64 (64-bit ARM)
arm (32-bit ARM)

os (Distribution)

eq, ne, in

Amazon
CentOS
Debian
Fedora
LinuxMint
Pop!_OS
RedHat
Rocky
Ubuntu

osVersionDetail.major (Major Version)

eq, ne, in, gt, ge, lt, le

Any valid numerical value.

created (Creation Date)

eq, ne, in, gt, ge, lt, le

Any date adhering to ISO-8601 formatting standards.

API Relevant Fields and Structure

Dynamic Groups API Overview

All of the dynamic groups-related API endpoint documentation can be found in the JumpCloud API (2.0) Documentation. User and device group endpoints are separate, and all dynamic group commands are in the context of either users or devices. There are no generic dynamic group endpoints that cover both users and devices.

Relevant Fields in Dynamic Groups API Endpoints

The core components of dynamic group management on the API schema are:

membershipMethod

  • STATIC - All changes to membership are managed by the administrator. This is the default value.

  • DYNAMIC_REVIEW_REQUIRED - JumpCloud will generate membership changes based on the group’s memberQuery, memberQueryExemptions, and current membership. The administrator must manually apply these suggestions to make membership changes.

  • DYNAMIC_AUTOMATED - JumpCloud will generate and automatically apply membership changes based on the group’s memberQuery, memberQueryExemptions, and current membership

memberQuery

Determines how a group's membership is evaluated for a dynamic group. Current considerations to keep in mind when building a memberQuery:

  • The only supported queryType is FilterQuery.

  • The filters field contains an array of filters built using eligible attributes, operators, and values detailed in the section below.

  • Currently, all filter conditions are joined by an implicit and operator.

  • The in operator expects a pipe (|) delimited list of values.

  • All values are provided as a string type.

For example, the following query

"memberQuery": {
    "queryType": "FilterQuery",
    "filters": [
      {
        "field": "attribute1",
        "operator": "eq",
        "value": "1"
      },
      {
        "field": "attribute2",
        "operator": "in",
        "value": "1|2|3"
      }
    ]

would behave similar to this sql clause:

WHERE attribute1 = 1 AND attribute2 IN(1, 2, 3)

memberQueryExemptions

An array of GraphObjects exempted from the query. When evaluating membership, JumpCloud will never add or remove an exempt member from the group. Their membership status can only be maintained manually via the admin. An exemption consists of an objectId and a type, as in this example:

"memberQueryExemptions": [
  {
    "id": "633ddf437046a60780ce898e",
    "type": "system"
  }
],

memberSuggestionsNotify

Determines whether nightly emails are sent notifying the admin of any pending operations. This is only applicable for DYNAMIC_REVIEW_REQUIRED groups.

Dynamic User Group Configuration/Management Examples

The following sections are meant to provide examples of completing certain tasks related to Dynamic User Group configuration and management.

Creating a new dynamic user group

In this example, we are creating a new dynamic user group where
name = groupUsingInOperator
membershipMethod = DYNAMIC_REVIEW_REQUIRED
memberQuery leverages several attributes in order to show how a complex filter can be used. In this example, we are filtering for members assigned to the Cost Centers 111, 222, and 333 whose department is Engineering.

POST https://console.jumpcloud.com/api/v2/usergroups

{
  "name": "groupUsingInOperator",
  "type": "user_group",
  "description": "A group using in operator for membership query.",
  "memberSuggestionsNotify": false,
  "membershipMethod": "DYNAMIC_REVIEW_REQUIRED",
  "memberQuery": {
    "queryType": "FilterQuery",
    "filters": [
      {
        "field": "costCenter",
        "operator": "in",
        "value": "111|222|333"
      },
      {
        "field": "department",
        "operator": "eq",
        "value": "Engineering"
      }
    ]
  }
}

Response 201

{
  "attributes": {
    "ldapGroups": [
      {
        "name": "groupUsingInOperator1"
      }
    ]
  },
  "id": "{id}",
  "name": "groupUsingInOperator",
  "type": "user_group",
  "email": "",
  "description": "A group using in operator for membership query.",
  "memberSuggestionsNotify": false,
  "membershipAutomated": false,
  "membershipMethod": "DYNAMIC_REVIEW_REQUIRED",
  "memberQuery": {
    "queryType": "FilterQuery",
    "filters": [
      {
        "field": "costCenter",
        "operator": "in",
        "value": "111|222|333"
      },
      {
        "field": "department",
        "operator": "eq",
        "value": "Engineering"
      }
    ]
  },
  "memberQueryExemptions": []
}

Changing a dynamic user group from "review required" to "automated"

In this example, we are changing the membershipMethod to DYNAMIC_AUTOMATED in line 6 so that user group membership changes don’t have to be reviewed and will update automatically.

PUT https://console.jumpcloud.com/api/v2/usergroups/{id}

{
  "name": "groupUsingInOperator",
  "type": "user_group",
  "description": "A group using in operator for membership query.",
  "memberSuggestionsNotify": false,
  "membershipMethod": "DYNAMIC_AUTOMATED",
  "memberQuery": {
    "queryType": "FilterQuery",
    "filters": [
      {
        "field": "costCenter",
        "operator": "in",
        "value": "111|222|333"
      },
      {
        "field": "department",
        "operator": "eq",
        "value": "Engineering"
      }
    ]
  }
}

Response 201

{
  "attributes": {
    "ldapGroups": [
      {
        "name": "groupUsingInOperator"
      }
    ]
  },
  "id": "{id}",
  "name": "groupUsingInOperator",
  "type": "user_group",
  "email": "",
  "description": "A group using in operator for membership query.",
  "memberSuggestionsNotify": false,
  "membershipAutomated": true,
  "membershipMethod": "DYNAMIC_AUTOMATED",
  "memberQuery": {
    "queryType": "FilterQuery",
    "filters": [
      {
        "field": "costCenter",
        "operator": "in",
        "value": "111|222|333"
      },
      {
        "field": "department",
        "operator": "eq",
        "value": "Engineering"
      }
    ]
  },
  "memberQueryExemptions": []
}

Disabling email notifications for "review required" dynamic user group

In this example, we are changing the group with membershipMethod set to DYNAMIC_REVIEW_REQUIRED to not send email notifications when there are group membership suggestions need to be reviewed. Do this by setting memberSuggestionsNotify in line 5 to false.

PUT https://console.jumpcloud.com/api/v2/usergroups/{id}

{
  "name": "groupUsingInOperator",
  "type": "user_group",
  "description": "A group using in operator for membership query.",
  "memberSuggestionsNotify": false,
  "membershipMethod": "DYNAMIC_REVIEW_REQUIRED",
  "memberQuery": {
    "queryType": "FilterQuery",
    "filters": [
      {
        "field": "costCenter",
        "operator": "in",
        "value": "111|222|333"
      },
      {
        "field": "department",
        "operator": "eq",
        "value": "Engineering"
      }
    ]
  }
}

Response 201

{
  "attributes": {
    "ldapGroups": [
      {
        "name": "groupUsingInOperator"
      }
    ]
  },
  "id": "{id}",
  "name": "groupUsingInOperator",
  "type": "user_group",
  "email": "",
  "description": "A group using in operator for membership query.",
  "memberSuggestionsNotify": false,
  "membershipAutomated": true,
  "membershipMethod": "DYNAMIC_REVIEW_REQUIRED",
  "memberQuery": {
    "queryType": "FilterQuery",
    "filters": [
      {
        "field": "costCenter",
        "operator": "in",
        "value": "111|222|333"
      },
      {
        "field": "department",
        "operator": "eq",
        "value": "Engineering"
      }
    ]
  }
}

Adding an exemption and adding the user to the dynamic user group

In this example, we are (1) adding an exemption to the user group so that it is ignored by the query rules and (2) adding the user to the group. By adding the exemption, the user is not automatically added to/removed from the group. A second intentional step must be taken to add the user to the group.

First, retrieve the user id’s for the users you want to exempt.

The list API can be used to get the user id, as well as other user attributes, in order to add the user to the exemption list.

POST https://console.jumpcloud.com/api/systemusers

-d '{
      "username":"{username}",
      "email":"{email_address}",
      "firstname":"{Name}",
      "lastname":"{Name}"
    }'

Response 201

{
  "totalCount": 1,
  "results": [
    {
      "account_locked": false,
      "account_locked_date": null,
      "activated": false,
      "addresses": [],
      "allow_public_key": true,
      "alternateEmail": null,
      "attributes": [],
      "company": "value1",
      "costCenter": "111",
      "department": "",
      "description": "example user",
      "disableDeviceMaxLoginAttempts": false,
      "displayname": "",
      "email": "example@example.com",
      "employeeIdentifier": null,
      "employeeType": "Employee",
      "enable_managed_uid": false,
      "enable_user_portal_multifactor": false,
      "external_dn": "",
      "external_source_type": "",
      "externally_managed": false,
      "firstname": "",
      "jobTitle": "dd",
      "lastname": "",
      "ldap_binding_user": false,
      "location": "",
      "managedAppleId": "",
      "manager": null,
      "mfa": {
        "exclusion": false,
        "configured": false
      },
      "middlename": "",
      "password_never_expires": false,
      "passwordless_sudo": false,
      "phoneNumbers": [],
      "samba_service_user": false,
      "ssh_keys": [],
      "state": "ACTIVATED",
      "sudo": false,
      "suspended": false,
      "systemUsername": "",
      "unix_guid": 5024,
      "unix_uid": 5024,
      "username": "exampleuser",
      "created": "2022-09-21T19:44:59.329Z",
      "organization": "{id}",
      "password_expired": false,
      "totp_enabled": false,
      "_id": "{id}",
      "id": "{id}",
      "mfaEnrollment": {
        "totpStatus": "NOT_ENROLLED",
        "webAuthnStatus": "NOT_ENROLLED",
        "pushStatus": "NOT_ENROLLED",
        "overallStatus": "NOT_ENROLLED"
      }
    }
  ]
}

After the user ids are retrieved, users can be added to the exemption list by updating the corresponding user group. Update the existing dynamic user group by setting memberQueryExemptions to an array of graph objects containing a user id and "type": "USER"

PUT https://console.jumpcloud.com/api/v2/usergroups/{id}

{
  "name": "groupUsingInOperator",
  "type": "user_group",
  "description": "A group using in operator for membership query.",
  "memberSuggestionsNotify": false,
  "membershipMethod": "DYNAMIC_AUTOMATED",
  "memberQuery": {
    "queryType": "FilterQuery",
    "filters": [
      {
        "field": "costCenter",
        "operator": "in",
        "value": "111|222|333"
      },
      {
        "field": "department",
        "operator": "eq",
        "value": "Engineering"
      }
    ]
  },
  "memberQueryExemptions": [
    {
      "type": "USER",
      "id": "{id}"
    },
    {
      "type": "USER",
      "id": "{id}"
    }
  ]
}

Response 201

{
  "attributes": {
    "ldapGroups": [
      {
        "name": "groupUsingInOperator"
      }
    ]
  },
  "id": "{id}",
  "name": "groupUsingInOperator",
  "type": "user_group",
  "email": "",
  "description": "A group using in operator for membership query.",
  "memberSuggestionsNotify": false,
  "membershipAutomated": true,
  "membershipMethod": "DYNAMIC_AUTOMATED",
  "memberQuery": {
    "queryType": "FilterQuery",
    "filters": [
      {
        "field": "costCenter",
        "operator": "in",
        "value": "111|222|333"
      },
      {
        "field": "department",
        "operator": "eq",
        "value": "Engineering"
      }
    ]
  },
  "memberQueryExemptions": [
    {
      "type": "USER",
      "id": "{id}"
    },
    {
      "type": "USER",
      "id": "{id}"
    }
  ]
}

Once a user is exempted from the group, they can be manually added/removed as a member without risk of being “re-associated” because of the memberQuery rules.

The following request adds the user to the group.

POST https://console.jumpcloud.com/api/v2/usergroups/{usergroup_id}/members

{
      "op":"add",
      "type":"user",
      "id":"{user_id}"
}

Response 201

[]

The user will remain in the group until the admin removes them or the exemption is removed and the user no longer meets the memberQuery rules for that group.

Approving a review required change in membership for a dynamic user group

In this example, we are highlighting how to approve membership changes where the user group membershipMethod is set to DYNAMIC_REVIEW_REQUIRED.

First, the admin needs to retrieve suggestions. This will consist of an operation (add or remove) and a graph object.

GET https://console.jumpcloud.com/api/v2/usergroups/{id}/suggestions?skip=0&limit=50"

Response 201

[
  {
    "op": "add",
    "object": {
      "type": "user",
      "id": "{id}"
    }
  },
  {
    "op": "remove",
    "object": {
      "type": "user",
      "id": "{id}"
    }
  }
]

Once the object Ids are retrieved in the first step, the corresponding suggestions can be applied using below request. The request body contains an array of objectIds that have a pending suggestion.

POST https://console.jumpcloud.com/api/v2/usergroups/63371a4d89e58400010f1395/suggestions

 {
  "user_ids":[
    "{id}",
    "{id}"]
}'

Response 201

{
  "object": {
    "suggestions_found": [
      "{id}",
      "{id}"],
    "suggestions_not_found": [
     ]
  }
}

The response will contain any objectIds that did not contain a suggestion in. the suggestions_not_found array. After the suggestions are retrieved, the admin can apply the suggestions that are found.

Adding a new rule to an existing dynamic user group

In this example, we are highlighting how to add another rule to an already existing dynamic user group by setting a new memberQuery. In this case, we want users whose location is Colorado.

PUT https://console.jumpcloud.com/api/v2/usergroups/{id}

{
  "name": "groupUsingInOperator",
  "type": "user_group",
  "description": "A group using in operator for membership query.",
  "memberSuggestionsNotify": false,
  "membershipMethod": "DYNAMIC_AUTOMATED",
  "memberQuery": {
    "queryType": "FilterQuery",
    "filters": [
      {
        "field": "costCenter",
        "operator": "in",
        "value": "111|222|333"
      },
      {
        "field": "department",
        "operator": "eq",
        "value": "Engineering"
      },
      {
        "field": "location",
        "operator": "eq",
        "value": "Colorado"
      }
    ]
  }
}

Response 201

{
  "attributes": {
    "ldapGroups": [
      {
        "name": "groupUsingInOperator"
      }
    ]
  },
  "id": "{id}",
  "name": "groupUsingInOperator",
  "type": "user_group",
  "email": "",
  "description": "A group using in operator for membership query.",
  "memberSuggestionsNotify": false,
  "membershipAutomated": true,
  "membershipMethod": "DYNAMIC_AUTOMATED",
  "memberQuery": {
    "queryType": "FilterQuery",
    "filters": [
      {
        "field": "costCenter",
        "operator": "in",
        "value": "111|222|333"
      },
      {
        "field": "department",
        "operator": "eq",
        "value": "Engineering"
      },
      {
        "field": "location",
        "operator": "eq",
        "value": "Colorado"
      }
    ]
  },
  "memberQueryExemptions": []
}

Dynamic Device Group Configuration/Management Examples

The following sections provide examples of completing certain tasks related to dynamic device group configuration and management.

Creating a new dynamic device group

In this example, we are creating a new dynamic device group where
name = Demo Dynamic Group
membershipMethod = DYNAMIC_REVIEW_REQUIRED
memberQuery leverages several attributes in order to show how a complex filter can be used. In this example, we are filtering for all JumpCloud-supported devices minus Rocky Linux, of all valid architectures whose current version is greater than 9 whose device record was created on or after 09:20:36Z on July 10, 2020.

POST https://console.jumpcloud.com/api/v2/systemgroups

{
    "name": "Demo Dynamic Group",
    "membershipMethod": "DYNAMIC_REVIEW_REQUIRED",
    "memberQuery":{
      "queryType":"FilterQuery",
      "filters":[
         {
            "field":"osFamily",
            "operator":"in",
            "value":"linux|darwin|windows|ios|android"
         },
         {
            "field":"archFamily",
            "operator":"in",
            "value":"amd64|383|arm64|arm"
         },
         {
            "field":"osVersionDetail.major",
            "operator":"gt",
            "value":"9"
         },
         {
            "field":"created",
            "operator":"ge",
            "value":"2020-07-10 09:30:26Z"
         },
         {
            "field":"os",
            "operator":"ne",
            "value":"Rocky"
         }
      ],
    ]
   }
}

Response: 201

{
    "attributes": null,
    "id": "{id}",
    "name": "Demo Dynamic Group",
    "type": "system_group",
    "email": "",
    "description": "",
    "memberSuggestionsNotify": false,
    "membershipAutomated": false,
    "membershipMethod": "DYNAMIC_REVIEW_REQUIRED",
    "memberQuery": {
        "queryType": "FilterQuery",
        "filters": [
            {
                "field": "osFamily",
                "operator": "in",
                "value": "linux|darwin|windows|ios|android"
            },
            {
                "field": "archFamily",
                "operator": "in",
                "value": "amd64|383|arm64|arm"
            },
            {
                "field": "osVersionDetail.major",
                "operator": "gt",
                "value": "0"
            },
            {
                "field": "created",
                "operator": "ge",
                "value": "2020-07-10 09:30:26Z"
            },
            {
                "field": "os",
                "operator": "ne",
                "value": "Rocky"
            }
        ]
    },
    "memberQueryExemptions": [
        {
            "type": "SYSTEM",
            "id": "633ddf437046a60780ce898e"
        }
    ]
}

Changing a dynamic device group from “review required” to “automated"

In this example, we are changing the membershipMethod to DYNAMIC_AUTOMATED in line 3 so that device group membership changes don’t have to be reviewed and will update automatically.

PUT https://console.jumpcloud.com/api/v2/systemgroups/{id}

{
    "name": "Demo Dynamic Group",
    "membershipMethod": "DYNAMIC_AUTOMATED",
    "memberQuery":{
      "queryType":"FilterQuery",
      "filters":[
         {
            "field":"osFamily",
            "operator":"in",
            "value":"linux"
         }
      ]
   }
}

Response: 200

{
    "attributes": null,
    "id": "{id}",
    "name": "Demo Dynamic Group",
    "type": "system_group",
    "email": "",
    "description": "",
    "memberSuggestionsNotify": false,
    "membershipAutomated": false,
    "membershipMethod": "DYNAMIC_AUTOMATED",
    "memberQuery": {
        "queryType": "FilterQuery",
        "filters": [
            {
                "field": "osFamily",
                "operator": "in",
                "value": "linux"
            }
        ]
    },
    "memberQueryExemptions": []
}

Adding an exemption and adding the device to the dynamic device group

In this example, we are (1) adding an exemption to the group so that it is ignored by the query rules and (2) adding the device to the group. By adding the exemption, the device does not automatically get added to the group. A second intentional step must be taken to add the device.

To update the existing group, set memberQueryExemptions to an the GraphObject with a system id and "type": "SYSTEM".

PUT https://console.jumpcloud.com/api/v2/systemgroups/{id}

{
    "name": "Demo Dynamic Group",
    "membershipMethod": "DYNAMIC_AUTOMATED",
    "memberQuery":{
      "queryType":"FilterQuery",
      "filters":[
         {
            "field":"osFamily",
            "operator":"in",
            "value":"linux"
         }
      ]
   },
   "memberQueryExemptions": [
        {
            "id": "633ddf437046a60780ce898e",
            "type": "SYSTEM"
        }
    ]
}

Response: 200

{
    "attributes": null,
    "id": "{id}",
    "name": "Demo Dynamic Group",
    "type": "system_group",
    "email": "",
    "description": "",
    "memberSuggestionsNotify": false,
    "membershipAutomated": true,
    "membershipMethod": "DYNAMIC_AUTOMATED",
    "memberQuery": {
        "queryType": "FilterQuery",
        "filters": [
            {
                "field": "osFamily",
                "operator": "in",
                "value": "linux"
            }
        ]
    },
    "memberQueryExemptions": [
        {
            "type": "SYSTEM",
            "id": "633ddf437046a60780ce898e"
        }
    ]
} 

Once a device is exempted from the group, it can be manually added/removed as a member without risk of being “re-associated” because of the memberQuery rules.

The following request adds the device to the group. The device will remain in the group until the admin removes it or the exemption is removed and the device no longer meets the FilterQuery rules for the device group.

PUT https://console.jumpcloud.com/api/v2/systemgroups/{id}/members

{
  "id": "633ddf437046a60780ce898e",
  "op": "add",
  "type": "system"
}

Response: 204

{}

Approving a review required change in membership for a dynamic device group

In this example, we are highlighting how to approve membership changes where the device group membershipMethod is set to DYNAMIC_REVIEW_REQUIRED.

First, retrieve membership suggestions. This will consist of an operation (add or remove) and a graph object.

GET https://console.jumpcloud.com/api/v2/systemgroups/{id}/suggestions

Response: 200

[
    {
        "op": "add",
        "object": {
            "type": "system",
            "id": "62e2d6c2a7bfcf8690f27254"
        }
    },
    {
        "op": "remove",
        "object": {
            "type": "system",
            "id": "62e2d9b4a7bfcf68c0f2740c"
        }
    }
]

After the suggestions are retrieved, you can apply the suggestions. The request body contains an array of objectIds with a pending suggestion.

POST https://console.jumpcloud.com/api/v2/systemgroups/{id}/suggestions

{
  "object_ids": [
    "62e2d6c2a7bfcf8690f27254"
  ]
}

Response: 200

{
    "object": {
        "suggestions_found": [
            "62e2d6c2a7bfcf8690f27254"
        ],
        "suggestions_not_found": []
    }
}

The response will contain any objectIds that did not contain a suggestion in the suggestions_not_found array.

Adding a new rule to an existing dynamic device group

In this example, we are highlighting how to add another rule to an already existing dynamic device group by setting a new memberQuery. In this example, we are adding a rule for macOS devices.

PUT https://console.jumpcloud.com/api/v2/systemgroups/{id}

{
    "name": "Demo Dynamic Group",
    "membershipMethod": "DYNAMIC_AUTOMATED",
    "memberQuery":{
      "queryType":"FilterQuery",
      "filters":[
         {
            "field":"osFamily",
            "operator":"in",
            "value":"darwin"
         }
      ]
   }
}

Response: 200

{
    "attributes": null,
    "id": "{id}",
    "name": "Demo Dynamic Group",
    "type": "system_group",
    "email": "",
    "description": "",
    "memberSuggestionsNotify": false,
    "membershipAutomated": false,
    "membershipMethod": "DYNAMIC_REVIEW_REQUIRED",
    "memberQuery": {
        "queryType": "FilterQuery",
        "filters": [
            {
                "field": "osFamily",
                "operator": "in",
                "value": "darwin"
            }
        ]
    },
    "memberQueryExemptions": []
}

Wrap Up

I hope that this helps provide some guidance around leveraging the JumpCloud API to build automation leveraging the Dynamic Groups feature. As you experiment and build with this capability, please post here in the community what you have built and learned.

0 REPLIES 0