|
| 1 | +--- |
| 2 | +pcx_content_type: how-to |
| 3 | +title: User Groups |
| 4 | +sidebar: |
| 5 | + badge: |
| 6 | + text: Beta |
| 7 | + order: 5 |
| 8 | +--- |
| 9 | + |
| 10 | +import { Tabs, TabItem } from '~/components'; |
| 11 | + |
| 12 | +User Groups are a collection of [account members](/fundamentals/setup/manage-members/manage/) that are treated equally from an access control perspective. User Groups can be assigned roles, with individual members in the group receiving all permissions of the roles assigned to the User Group. |
| 13 | + |
| 14 | +:::note |
| 15 | +If you use the Cloudflare Dashboard SCIM integration, you can sync Groups from an upstream Identity Provider via SCIM. This allows you to centralize user and group management at your identity provider. |
| 16 | + |
| 17 | +Additionally, when you manage User Groups with SCIM, you cannot change the name, members, or delete a group through either the Cloudflare Dashboard or API. |
| 18 | +::: |
| 19 | + |
| 20 | +## Create a User Group manually |
| 21 | + |
| 22 | +1. Log in to the [Cloudflare Dashboard](https://dash.cloudflare.com) and select your account. |
| 23 | +2. Go to **Manage Account** > **Members**. |
| 24 | +3. To opt-in to the User Groups Public Beta, select the **Try User Groups** button. Once clicked, the UI will update and a **Groups** tab will appear. |
| 25 | +4. Select the **Groups** tab. |
| 26 | +5. Select **Create a Group** and enter a name and description for your new group. |
| 27 | +6. Select **Create group** to confirm your changes. The **Group members** ta displays. |
| 28 | +7. Select **Add members**. |
| 29 | +8. Select the relevant members you want to include in the group and select **Add to Group**. |
| 30 | + |
| 31 | +### Assign a Permission Policy |
| 32 | + |
| 33 | +With your Group created, you can now add a [Permission Policy](/fundamentals/setup/manage-members/policies/) to your Group. |
| 34 | + |
| 35 | +<Tabs syncKey="dashPlusAPI"> <TabItem label="Dashboard"> |
| 36 | + |
| 37 | +1. In the **Groups** tab under **Permission policies**, select **Add a Policy**. |
| 38 | +2. Specify the scope and permissions you want applied to the members of the group. |
| 39 | +3. Select **Create Policy** to apply it to the group. You return to the **Permission policies** for your Group. |
| 40 | + |
| 41 | +</TabItem> <TabItem label="API"> |
| 42 | + |
| 43 | +Using the role identifiers from the previous section, you can create a group policy. |
| 44 | + |
| 45 | +`export ADMIN_ROLE='...' # id field from admin or desired role entry from permission_groups API response` |
| 46 | + |
| 47 | +```curl title="Example request" |
| 48 | +$ cat <<-PAYLOAD | curl -XPUT -H "Authorization: Bearer $AOT" -H "Content-type: application/json" --data-binary @- https://api.cloudflare.com/client/v4/accounts/$ACCT/iam/user_groups/$PUSHED_GROUP | jq . |
| 49 | +{ |
| 50 | + "policies": [ |
| 51 | + { |
| 52 | + "access": "allow", |
| 53 | + "permission_groups": [{"id": "$ADMIN_ROLE"}], |
| 54 | + "resource_groups": [{ |
| 55 | + "scope": { |
| 56 | + "key": "com.cloudflare.api.account.$ACCT", |
| 57 | + "objects": [{"key":"*"}] |
| 58 | + } |
| 59 | + }] |
| 60 | + } |
| 61 | + ] |
| 62 | +} |
| 63 | +PAYLOAD |
| 64 | +``` |
| 65 | + |
| 66 | +**Reset a policy to an empty state** |
| 67 | + |
| 68 | +If you made a mistake while creating the group policy or need to reset the policy to an empty state, send another PUT request to the group API with an empty policy array to overwrite with your new policy. |
| 69 | + |
| 70 | +```curl |
| 71 | +$ cat <<-PAYLOAD | curl -XPUT -H "Authorization: Bearer $AOT" -H "Content-type: application/json" --data-binary @- https://api.cloudflare.com/client/v4/accounts/$ACCT/iam/user_groups/$PUSHED_GROUP | jq . |
| 72 | +{ |
| 73 | + "policies": [] |
| 74 | +} |
| 75 | +PAYLOAD |
| 76 | +``` |
| 77 | + |
| 78 | +</TabItem> </Tabs> |
| 79 | + |
| 80 | +## Create a User Group with SCIM |
| 81 | + |
| 82 | +Customers with the SCIM integration configured can sync User Groups from an upstream identity provider to Cloudflare. Cloudflare's SCIM integration requires one external application per account. |
| 83 | + |
| 84 | +:::note |
| 85 | +Cloudflare's SCIM integration requires one external application per account. |
| 86 | +::: |
| 87 | + |
| 88 | +To set up a user group with SCIM, refer to the Provisioning with SCIM guide. |
| 89 | + |
| 90 | +### Set up permissions for User Groups |
| 91 | + |
| 92 | +After a user group is created either manually in Cloudflare dashboard or through SCIM integration the final step is to attach permissions to it. |
| 93 | + |
| 94 | +<Tabs syncKey="dashPlusAPI"> <TabItem label="Dashboard"> |
| 95 | + |
| 96 | +1. Go to **Manage members** > **Members** > **User groups**. |
| 97 | +2. Select the user group you want to attach permissions to. |
| 98 | +3. Select the **Permission policies** tab and select **Add policy**. |
| 99 | +4. Choose the scope and role that you want to apply to the policy. |
| 100 | +5. Select **Save** to apply the policy. |
| 101 | + |
| 102 | +</TabItem> <TabItem label="API"> |
| 103 | + |
| 104 | +Before you begin, confirm the groups that were created internally or have been pushed to Cloudflare by using the command below. |
| 105 | + |
| 106 | +**1. Get user groups** |
| 107 | + |
| 108 | +```curl title="Example request" |
| 109 | +$ curl -X GET -H "Authorization: Bearer $AOT" https://api.cloudflare.com/client/v4/accounts/$ACCT/iam/user_groups | jq . |
| 110 | +``` |
| 111 | + |
| 112 | +```curl title="Example response" |
| 113 | +{ |
| 114 | + "errors": [], |
| 115 | + "messages": [], |
| 116 | + "result": [ |
| 117 | + { |
| 118 | + "created_on": "2025-01-24T15:31:36.759979Z", |
| 119 | + "id": "f234f49f66df4db8864c5189fe78c87f", |
| 120 | + "modified_on": "2025-01-24T15:35:50.151764Z", |
| 121 | + "name": "My Cool Demo Group", |
| 122 | + "status": "V" |
| 123 | + }, |
| 124 | + { |
| 125 | + "created_on": "2025-01-16T20:43:01.019311Z", |
| 126 | + "id": "7148c1e4d9f247f5b6dcd3ef20f998f9", |
| 127 | + "modified_on": "2025-01-16T20:44:07.627233Z", |
| 128 | + "name": "My Cool Demo Group, now with policies!", |
| 129 | + "policies": [ |
| 130 | + { |
| 131 | + "access": "allow", |
| 132 | + "created_on": "2025-01-16T20:44:07.627233Z", |
| 133 | + "id": "8d82cf8c15c64e07a4bee58e00d80bca", |
| 134 | + "modified_on": "2025-01-16T20:44:07.627233Z", |
| 135 | + "permission_groups": [ |
| 136 | + { |
| 137 | + "created_on": "2023-06-21T18:58:29.907496Z", |
| 138 | + "id": "a1a099e3256942259bfde18c688b67d5", |
| 139 | + "meta": { |
| 140 | + "description": "Grants write access to Page Shield for domain", |
| 141 | + "editable": "false", |
| 142 | + "label": "domain_page_shield", |
| 143 | + "scopes": "com.cloudflare.api.account.zone" |
| 144 | + }, |
| 145 | + "modified_on": "2023-06-21T18:58:29.907496Z", |
| 146 | + "name": "Domain Page Shield", |
| 147 | + "permissions": ["dev note: snipped for length"], |
| 148 | + "status": "V" |
| 149 | + } |
| 150 | + ], |
| 151 | + "resource_groups": [ |
| 152 | + { |
| 153 | + "created_on": "2025-01-16T20:44:07.627233Z", |
| 154 | + "modified_on": "2025-01-16T20:44:07.627233Z", |
| 155 | + "scope": { |
| 156 | + "key": "com.cloudflare.api.account.a3324a084cd290080b563ab39c91545a", |
| 157 | + "objects": [ |
| 158 | + { |
| 159 | + "key": "*" |
| 160 | + } |
| 161 | + ] |
| 162 | + } |
| 163 | + } |
| 164 | + ], |
| 165 | + "status": "V" |
| 166 | + } |
| 167 | + ], |
| 168 | + "status": "V" |
| 169 | + } |
| 170 | + ], |
| 171 | + "result_info": { |
| 172 | + "count": 2, |
| 173 | + "page": 1, |
| 174 | + "per_page": 100, |
| 175 | + "total_count": 2, |
| 176 | + "total_pages": 1 |
| 177 | + }, |
| 178 | + "success": true |
| 179 | +} |
| 180 | +``` |
| 181 | + |
| 182 | +**2. Make a query against the resource ID** |
| 183 | + |
| 184 | +Locate the tag of the group you pushed from the IdP and use it to make a direct query against its resource ID: |
| 185 | + |
| 186 | +`export PUSHED_GROUP='...' # Pull this value from the "id" json field in the group list response` |
| 187 | + |
| 188 | +```curl title="Example request" |
| 189 | +$ curl -XGET -H "Authorization: Bearer $AOT" https://api.cloudflare.com/client/v4/accounts/$ACCT/iam/user_groups/$PUSHED_GROUP | jq . |
| 190 | +``` |
| 191 | + |
| 192 | +The response for this should have the group name that was specified in the identity provider with no attached policies. |
| 193 | + |
| 194 | +**3. Review available permission groups** |
| 195 | + |
| 196 | +Before you modify the group's policies, review the available permission groups (roles) on the account by querying its API. |
| 197 | + |
| 198 | +```curl title="Example request" |
| 199 | +$ curl -XGET -H "Authorization: Bearer $DEMO_AOT" https://api.cloudflare.com/client/v4/accounts/$ACCT/iam/permission_groups | jq . |
| 200 | +``` |
| 201 | + |
| 202 | +```curl title="Example response" |
| 203 | +{ |
| 204 | + "result": [ |
| 205 | + { |
| 206 | + "id": "1a0fc8bdeae24387b64d5b8de1ad052a", |
| 207 | + "name": "Administrator Read Only", |
| 208 | + "status": "V", |
| 209 | + "meta": { |
| 210 | + "description": "Can access the full account in read-only mode.", |
| 211 | + "editable": "false", |
| 212 | + "label": "admin_readonly", |
| 213 | + "scopes": "com.cloudflare.api.account" |
| 214 | + }, |
| 215 | + "created_on": "2020-07-06T12:19:13.099114Z", |
| 216 | + "modified_on": "2020-10-13T11:18:00.208228Z" |
| 217 | + }, |
| 218 | + { |
| 219 | + "id": "ce2c69b09baf4ca38223910a8b7e07a9", |
| 220 | + "name": "Administrator", |
| 221 | + "status": "V", |
| 222 | + "meta": { |
| 223 | + "description": "Can access the full account, except for membership management and billing.", |
| 224 | + "editable": "false", |
| 225 | + "label": "admin", |
| 226 | + "scopes": "com.cloudflare.api.account" |
| 227 | + }, |
| 228 | + "created_on": "2020-07-06T12:19:13.099114Z", |
| 229 | + "modified_on": "2020-10-13T11:18:00.208228Z" |
| 230 | + } |
| 231 | + ], |
| 232 | + "success": true, |
| 233 | + "errors": [], |
| 234 | + "messages": [] |
| 235 | +} |
| 236 | +``` |
| 237 | + |
| 238 | +:::note |
| 239 | +These permission groups are from our staging environment and tags will not function in your production deployment. |
| 240 | +::: |
| 241 | + |
| 242 | +</TabItem> </Tabs> |
| 243 | + |
| 244 | +## Inspect Group Members |
| 245 | + |
| 246 | +To verify the IdP synchronized the group and user members pushed in the SCIM operation, query the Group Members API. |
| 247 | + |
| 248 | +```curl title="Example request" |
| 249 | +$ curl -XGET -H "Authorization: Bearer $DEMO_AOT" https://api.cloudflare.com/client/v4/accounts/$ACCT/iam/user_groups/$PUSHED_GROUP/members | jq . |
| 250 | +``` |
| 251 | + |
| 252 | +```curl title="Example response" |
| 253 | +{ |
| 254 | + "result": [ |
| 255 | + { |
| 256 | + "id": "a4366a09c43a0b0c4606dc5528472bb6", |
| 257 | + |
| 258 | + }, |
| 259 | + { |
| 260 | + "id": "0329c17f6c13f5202dc38d2036efb1a9", |
| 261 | + |
| 262 | + } |
| 263 | + ], |
| 264 | + "result_info": { |
| 265 | + "page": 1, |
| 266 | + "per_page": 100, |
| 267 | + "total_pages": 1, |
| 268 | + "count": 2, |
| 269 | + "total_count": 2 |
| 270 | + }, |
| 271 | + "success": true, |
| 272 | + "errors": [], |
| 273 | + "messages": [] |
| 274 | +} |
| 275 | +``` |
0 commit comments