feat: synchronize oidc user roles (#8595)

* feat: oidc user role sync
User roles come from oidc claims. Prevent manual user role changes
if set.
* allow mapping 1:many
This commit is contained in:
Steven Masley
2023-07-24 08:34:24 -04:00
committed by GitHub
parent 94541d201f
commit f827829afe
38 changed files with 596 additions and 46 deletions

1
docs/api/audit.md generated
View File

@@ -63,6 +63,7 @@ curl -X GET http://coder-server:8080/api/v2/audit?q=string \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{

40
docs/api/enterprise.md generated
View File

@@ -182,6 +182,7 @@ curl -X GET http://coder-server:8080/api/v2/groups/{group} \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -241,6 +242,7 @@ curl -X DELETE http://coder-server:8080/api/v2/groups/{group} \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -300,6 +302,7 @@ curl -X PATCH http://coder-server:8080/api/v2/groups/{group} \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -434,6 +437,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -473,6 +477,7 @@ Status Code **200**
| `»» email` | string(email) | true | | |
| `»» id` | string(uuid) | true | | |
| `»» last_seen_at` | string(date-time) | false | | |
| `»» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | |
| `»» organization_ids` | array | false | | |
| `»» roles` | array | false | | |
| `»»» display_name` | string | false | | |
@@ -485,10 +490,15 @@ Status Code **200**
#### Enumerated Values
| Property | Value |
| -------- | ----------- |
| `status` | `active` |
| `status` | `suspended` |
| Property | Value |
| ------------ | ----------- |
| `login_type` | `password` |
| `login_type` | `github` |
| `login_type` | `oidc` |
| `login_type` | `token` |
| `login_type` | `none` |
| `status` | `active` |
| `status` | `suspended` |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
@@ -538,6 +548,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/groups
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -598,6 +609,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups/
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -959,6 +971,7 @@ curl -X PATCH http://coder-server:8080/api/v2/scim/v2/Users/{id} \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -1010,6 +1023,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/acl \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"role": "admin",
"roles": [
@@ -1042,6 +1056,7 @@ Status Code **200**
| `» email` | string(email) | true | | |
| `» id` | string(uuid) | true | | |
| `» last_seen_at` | string(date-time) | false | | |
| `» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | |
| `» organization_ids` | array | false | | |
| `» role` | [codersdk.TemplateRole](schemas.md#codersdktemplaterole) | false | | |
| `» roles` | array | false | | |
@@ -1052,12 +1067,17 @@ Status Code **200**
#### Enumerated Values
| Property | Value |
| -------- | ----------- |
| `role` | `admin` |
| `role` | `use` |
| `status` | `active` |
| `status` | `suspended` |
| Property | Value |
| ------------ | ----------- |
| `login_type` | `password` |
| `login_type` | `github` |
| `login_type` | `oidc` |
| `login_type` | `token` |
| `login_type` | `none` |
| `role` | `admin` |
| `role` | `use` |
| `status` | `active` |
| `status` | `suspended` |
To perform this operation, you must be authenticated. [Learn more](authentication.md).

3
docs/api/general.md generated
View File

@@ -279,6 +279,9 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \
"issuer_url": "string",
"scopes": ["string"],
"sign_in_text": "string",
"user_role_field": "string",
"user_role_mapping": {},
"user_roles_default": ["string"],
"username_field": "string"
},
"pg_connection_url": "string",

21
docs/api/schemas.md generated
View File

@@ -1000,6 +1000,7 @@
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -1076,6 +1077,7 @@
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -2006,6 +2008,9 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
"issuer_url": "string",
"scopes": ["string"],
"sign_in_text": "string",
"user_role_field": "string",
"user_role_mapping": {},
"user_roles_default": ["string"],
"username_field": "string"
},
"pg_connection_url": "string",
@@ -2359,6 +2364,9 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
"issuer_url": "string",
"scopes": ["string"],
"sign_in_text": "string",
"user_role_field": "string",
"user_role_mapping": {},
"user_roles_default": ["string"],
"username_field": "string"
},
"pg_connection_url": "string",
@@ -2649,6 +2657,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -2865,6 +2874,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -3223,6 +3233,9 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
"issuer_url": "string",
"scopes": ["string"],
"sign_in_text": "string",
"user_role_field": "string",
"user_role_mapping": {},
"user_roles_default": ["string"],
"username_field": "string"
}
```
@@ -3245,6 +3258,9 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
| `issuer_url` | string | false | | |
| `scopes` | array of string | false | | |
| `sign_in_text` | string | false | | |
| `user_role_field` | string | false | | |
| `user_role_mapping` | object | false | | |
| `user_roles_default` | array of string | false | | |
| `username_field` | string | false | | |
## codersdk.Organization
@@ -4304,6 +4320,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"role": "admin",
"roles": [
@@ -4326,6 +4343,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
| `email` | string | true | | |
| `id` | string | true | | |
| `last_seen_at` | string | false | | |
| `login_type` | [codersdk.LoginType](#codersdklogintype) | false | | |
| `organization_ids` | array of string | false | | |
| `role` | [codersdk.TemplateRole](#codersdktemplaterole) | false | | |
| `roles` | array of [codersdk.Role](#codersdkrole) | false | | |
@@ -4352,6 +4370,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -4821,6 +4840,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -4842,6 +4862,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
| `email` | string | true | | |
| `id` | string | true | | |
| `last_seen_at` | string | false | | |
| `login_type` | [codersdk.LoginType](#codersdklogintype) | false | | |
| `organization_ids` | array of string | false | | |
| `roles` | array of [codersdk.Role](#codersdkrole) | false | | |
| `status` | [codersdk.UserStatus](#codersdkuserstatus) | false | | |

19
docs/api/templates.md generated
View File

@@ -380,6 +380,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -461,6 +462,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -566,6 +568,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templa
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -878,6 +881,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -938,6 +942,7 @@ Status Code **200**
| `»» email` | string(email) | true | | |
| `»» id` | string(uuid) | true | | |
| `»» last_seen_at` | string(date-time) | false | | |
| `»» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | |
| `»» organization_ids` | array | false | | |
| `»» roles` | array | false | | |
| `»»» display_name` | string | false | | |
@@ -972,6 +977,11 @@ Status Code **200**
| Property | Value |
| ------------ | ----------------------------- |
| `login_type` | `password` |
| `login_type` | `github` |
| `login_type` | `oidc` |
| `login_type` | `token` |
| `login_type` | `none` |
| `status` | `active` |
| `status` | `suspended` |
| `error_code` | `MISSING_TEMPLATE_PARAMETER` |
@@ -1073,6 +1083,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions/{templ
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -1133,6 +1144,7 @@ Status Code **200**
| `»» email` | string(email) | true | | |
| `»» id` | string(uuid) | true | | |
| `»» last_seen_at` | string(date-time) | false | | |
| `»» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | |
| `»» organization_ids` | array | false | | |
| `»» roles` | array | false | | |
| `»»» display_name` | string | false | | |
@@ -1167,6 +1179,11 @@ Status Code **200**
| Property | Value |
| ------------ | ----------------------------- |
| `login_type` | `password` |
| `login_type` | `github` |
| `login_type` | `oidc` |
| `login_type` | `token` |
| `login_type` | `none` |
| `status` | `active` |
| `status` | `suspended` |
| `error_code` | `MISSING_TEMPLATE_PARAMETER` |
@@ -1212,6 +1229,7 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion} \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -1302,6 +1320,7 @@ curl -X PATCH http://coder-server:8080/api/v2/templateversions/{templateversion}
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{

9
docs/api/users.md generated
View File

@@ -36,6 +36,7 @@ curl -X GET http://coder-server:8080/api/v2/users \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -101,6 +102,7 @@ curl -X POST http://coder-server:8080/api/v2/users \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -359,6 +361,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user} \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -409,6 +412,7 @@ curl -X DELETE http://coder-server:8080/api/v2/users/{user} \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -1002,6 +1006,7 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/profile \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -1052,6 +1057,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/roles \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -1112,6 +1118,7 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/roles \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -1162,6 +1169,7 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/status/activate \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{
@@ -1212,6 +1220,7 @@ curl -X PUT http://coder-server:8080/api/v2/users/{user}/status/suspend \
"email": "user@example.com",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "password",
"organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"],
"roles": [
{

31
docs/cli/server.md generated
View File

@@ -522,6 +522,37 @@ Issuer URL to use for Login with OIDC.
Scopes to grant when authenticating with OIDC.
### --oidc-user-role-default
| | |
| ----------- | ------------------------------------------ |
| Type | <code>string-array</code> |
| Environment | <code>$CODER_OIDC_USER_ROLE_DEFAULT</code> |
| YAML | <code>oidc.userRoleDefault</code> |
If user role sync is enabled, these roles are always included for all authenticated users. The 'member' role is always assigned.
### --oidc-user-role-field
| | |
| ----------- | ---------------------------------------- |
| Type | <code>string</code> |
| Environment | <code>$CODER_OIDC_USER_ROLE_FIELD</code> |
| YAML | <code>oidc.userRoleField</code> |
This field must be set if using the user roles sync feature. Set this to the name of the claim used to store the user's role. The roles should be sent as an array of strings.
### --oidc-user-role-mapping
| | |
| ----------- | ------------------------------------------ |
| Type | <code>struct[map[string][]string]</code> |
| Environment | <code>$CODER_OIDC_USER_ROLE_MAPPING</code> |
| YAML | <code>oidc.userRoleMapping</code> |
| Default | <code>{}</code> |
A map of the OIDC passed in user roles and the groups in Coder it should map to. This is useful if the group names do not match. If mapped to the empty string, the role will ignored.
### --oidc-username-field
| | |