mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
feat: implement patch and get api methods for role sync (#14692)
* feat: implement patch and get api methods for role sync
This commit is contained in:
167
coderd/apidoc/docs.go
generated
167
coderd/apidoc/docs.go
generated
@ -3155,7 +3155,7 @@ const docTemplate = `{
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/idpsync.GroupSyncSettings"
|
||||
"$ref": "#/definitions/codersdk.GroupSyncSettings"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3188,7 +3188,75 @@ const docTemplate = `{
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/idpsync.GroupSyncSettings"
|
||||
"$ref": "#/definitions/codersdk.GroupSyncSettings"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/organizations/{organization}/settings/idpsync/roles": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Enterprise"
|
||||
],
|
||||
"summary": "Get role IdP Sync settings by organization",
|
||||
"operationId": "get-role-idp-sync-settings-by-organization",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Organization ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.RoleSyncSettings"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Enterprise"
|
||||
],
|
||||
"summary": "Update role IdP Sync settings by organization",
|
||||
"operationId": "update-role-idp-sync-settings-by-organization",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Organization ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.RoleSyncSettings"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10523,6 +10591,44 @@ const docTemplate = `{
|
||||
"GroupSourceOIDC"
|
||||
]
|
||||
},
|
||||
"codersdk.GroupSyncSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"auto_create_missing_groups": {
|
||||
"description": "AutoCreateMissing controls whether groups returned by the OIDC provider\nare automatically created in Coder if they are missing.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"field": {
|
||||
"description": "Field selects the claim field to be used as the created user's\ngroups. If the group field is the empty string, then no group updates\nwill ever come from the OIDC provider.",
|
||||
"type": "string"
|
||||
},
|
||||
"legacy_group_name_mapping": {
|
||||
"description": "LegacyNameMapping is deprecated. It remaps an IDP group name to\na Coder group name. Since configuration is now done at runtime,\ngroup IDs are used to account for group renames.\nFor legacy configurations, this config option has to remain.\nDeprecated: Use Mapping instead.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"mapping": {
|
||||
"description": "Mapping maps from an OIDC group --\u003e Coder group ID",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"regex_filter": {
|
||||
"description": "RegexFilter is a regular expression that filters the groups returned by\nthe OIDC provider. Any group not matched by this regex will be ignored.\nIf the group filter is nil, then no group filtering will occur.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/regexp.Regexp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.Healthcheck": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -12238,6 +12344,25 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.RoleSyncSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"field": {
|
||||
"description": "Field selects the claim field to be used as the created user's\ngroups. If the group field is the empty string, then no group updates\nwill ever come from the OIDC provider.",
|
||||
"type": "string"
|
||||
},
|
||||
"mapping": {
|
||||
"description": "Mapping maps from an OIDC group --\u003e Coder organization role",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.SSHConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -15253,44 +15378,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"idpsync.GroupSyncSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"auto_create_missing_groups": {
|
||||
"description": "AutoCreateMissing controls whether groups returned by the OIDC provider\nare automatically created in Coder if they are missing.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"field": {
|
||||
"description": "Field selects the claim field to be used as the created user's\ngroups. If the group field is the empty string, then no group updates\nwill ever come from the OIDC provider.",
|
||||
"type": "string"
|
||||
},
|
||||
"legacy_group_name_mapping": {
|
||||
"description": "LegacyNameMapping is deprecated. It remaps an IDP group name to\na Coder group name. Since configuration is now done at runtime,\ngroup IDs are used to account for group renames.\nFor legacy configurations, this config option has to remain.\nDeprecated: Use Mapping instead.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"mapping": {
|
||||
"description": "Mapping maps from an OIDC group --\u003e Coder group ID",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"regex_filter": {
|
||||
"description": "RegexFilter is a regular expression that filters the groups returned by\nthe OIDC provider. Any group not matched by this regex will be ignored.\nIf the group filter is nil, then no group filtering will occur.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/regexp.Regexp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"key.NodePublic": {
|
||||
"type": "object"
|
||||
},
|
||||
|
159
coderd/apidoc/swagger.json
generated
159
coderd/apidoc/swagger.json
generated
@ -2773,7 +2773,7 @@
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/idpsync.GroupSyncSettings"
|
||||
"$ref": "#/definitions/codersdk.GroupSyncSettings"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2802,7 +2802,67 @@
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/idpsync.GroupSyncSettings"
|
||||
"$ref": "#/definitions/codersdk.GroupSyncSettings"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/organizations/{organization}/settings/idpsync/roles": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": ["application/json"],
|
||||
"tags": ["Enterprise"],
|
||||
"summary": "Get role IdP Sync settings by organization",
|
||||
"operationId": "get-role-idp-sync-settings-by-organization",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Organization ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.RoleSyncSettings"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": ["application/json"],
|
||||
"tags": ["Enterprise"],
|
||||
"summary": "Update role IdP Sync settings by organization",
|
||||
"operationId": "update-role-idp-sync-settings-by-organization",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Organization ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.RoleSyncSettings"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9445,6 +9505,44 @@
|
||||
"enum": ["user", "oidc"],
|
||||
"x-enum-varnames": ["GroupSourceUser", "GroupSourceOIDC"]
|
||||
},
|
||||
"codersdk.GroupSyncSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"auto_create_missing_groups": {
|
||||
"description": "AutoCreateMissing controls whether groups returned by the OIDC provider\nare automatically created in Coder if they are missing.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"field": {
|
||||
"description": "Field selects the claim field to be used as the created user's\ngroups. If the group field is the empty string, then no group updates\nwill ever come from the OIDC provider.",
|
||||
"type": "string"
|
||||
},
|
||||
"legacy_group_name_mapping": {
|
||||
"description": "LegacyNameMapping is deprecated. It remaps an IDP group name to\na Coder group name. Since configuration is now done at runtime,\ngroup IDs are used to account for group renames.\nFor legacy configurations, this config option has to remain.\nDeprecated: Use Mapping instead.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"mapping": {
|
||||
"description": "Mapping maps from an OIDC group --\u003e Coder group ID",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"regex_filter": {
|
||||
"description": "RegexFilter is a regular expression that filters the groups returned by\nthe OIDC provider. Any group not matched by this regex will be ignored.\nIf the group filter is nil, then no group filtering will occur.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/regexp.Regexp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.Healthcheck": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -11070,6 +11168,25 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.RoleSyncSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"field": {
|
||||
"description": "Field selects the claim field to be used as the created user's\ngroups. If the group field is the empty string, then no group updates\nwill ever come from the OIDC provider.",
|
||||
"type": "string"
|
||||
},
|
||||
"mapping": {
|
||||
"description": "Mapping maps from an OIDC group --\u003e Coder organization role",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.SSHConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -13906,44 +14023,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"idpsync.GroupSyncSettings": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"auto_create_missing_groups": {
|
||||
"description": "AutoCreateMissing controls whether groups returned by the OIDC provider\nare automatically created in Coder if they are missing.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"field": {
|
||||
"description": "Field selects the claim field to be used as the created user's\ngroups. If the group field is the empty string, then no group updates\nwill ever come from the OIDC provider.",
|
||||
"type": "string"
|
||||
},
|
||||
"legacy_group_name_mapping": {
|
||||
"description": "LegacyNameMapping is deprecated. It remaps an IDP group name to\na Coder group name. Since configuration is now done at runtime,\ngroup IDs are used to account for group renames.\nFor legacy configurations, this config option has to remain.\nDeprecated: Use Mapping instead.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"mapping": {
|
||||
"description": "Mapping maps from an OIDC group --\u003e Coder group ID",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"regex_filter": {
|
||||
"description": "RegexFilter is a regular expression that filters the groups returned by\nthe OIDC provider. Any group not matched by this regex will be ignored.\nIf the group filter is nil, then no group filtering will occur.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/regexp.Regexp"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"key.NodePublic": {
|
||||
"type": "object"
|
||||
},
|
||||
|
@ -55,7 +55,8 @@ type IDPSync interface {
|
||||
SiteRoleSyncEnabled() bool
|
||||
// RoleSyncSettings is similar to GroupSyncSettings. See GroupSyncSettings for
|
||||
// rational.
|
||||
RoleSyncSettings() runtimeconfig.RuntimeEntry[*RoleSyncSettings]
|
||||
RoleSyncSettings(ctx context.Context, orgID uuid.UUID, db database.Store) (*RoleSyncSettings, error)
|
||||
UpdateRoleSettings(ctx context.Context, orgID uuid.UUID, db database.Store, settings RoleSyncSettings) error
|
||||
// ParseRoleClaims takes claims from an OIDC provider, and returns the params
|
||||
// for role syncing. Most of the logic happens in SyncRoles.
|
||||
ParseRoleClaims(ctx context.Context, mergedClaims jwt.MapClaims) (RoleParams, *HTTPError)
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/rbac/rolestore"
|
||||
"github.com/coder/coder/v2/coderd/runtimeconfig"
|
||||
"github.com/coder/coder/v2/coderd/util/slice"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
)
|
||||
|
||||
type RoleParams struct {
|
||||
@ -41,8 +42,26 @@ func (AGPLIDPSync) SiteRoleSyncEnabled() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (s AGPLIDPSync) RoleSyncSettings() runtimeconfig.RuntimeEntry[*RoleSyncSettings] {
|
||||
return s.Role
|
||||
func (s AGPLIDPSync) UpdateRoleSettings(ctx context.Context, orgID uuid.UUID, db database.Store, settings RoleSyncSettings) error {
|
||||
orgResolver := s.Manager.OrganizationResolver(db, orgID)
|
||||
err := s.SyncSettings.Role.SetRuntimeValue(ctx, orgResolver, &settings)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("update role sync settings: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s AGPLIDPSync) RoleSyncSettings(ctx context.Context, orgID uuid.UUID, db database.Store) (*RoleSyncSettings, error) {
|
||||
rlv := s.Manager.OrganizationResolver(db, orgID)
|
||||
settings, err := s.Role.Resolve(ctx, rlv)
|
||||
if err != nil {
|
||||
if !xerrors.Is(err, runtimeconfig.ErrEntryNotFound) {
|
||||
return nil, xerrors.Errorf("resolve role sync settings: %w", err)
|
||||
}
|
||||
return &RoleSyncSettings{}, nil
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
func (s AGPLIDPSync) ParseRoleClaims(_ context.Context, _ jwt.MapClaims) (RoleParams, *HTTPError) {
|
||||
@ -85,15 +104,12 @@ func (s AGPLIDPSync) SyncRoles(ctx context.Context, db database.Store, user data
|
||||
allExpected := make([]rbac.RoleIdentifier, 0)
|
||||
for _, member := range orgMemberships {
|
||||
orgID := member.OrganizationMember.OrganizationID
|
||||
orgResolver := s.Manager.OrganizationResolver(tx, orgID)
|
||||
settings, err := s.RoleSyncSettings().Resolve(ctx, orgResolver)
|
||||
settings, err := s.RoleSyncSettings(ctx, orgID, tx)
|
||||
if err != nil {
|
||||
if !xerrors.Is(err, runtimeconfig.ErrEntryNotFound) {
|
||||
return xerrors.Errorf("resolve group sync settings: %w", err)
|
||||
}
|
||||
// No entry means no role syncing for this organization
|
||||
continue
|
||||
}
|
||||
|
||||
if settings.Field == "" {
|
||||
// Explicitly disabled role sync for this organization
|
||||
continue
|
||||
@ -261,14 +277,7 @@ func (AGPLIDPSync) RolesFromClaim(field string, claims jwt.MapClaims) ([]string,
|
||||
return parsedRoles, nil
|
||||
}
|
||||
|
||||
type RoleSyncSettings struct {
|
||||
// Field selects the claim field to be used as the created user's
|
||||
// groups. If the group field is the empty string, then no group updates
|
||||
// will ever come from the OIDC provider.
|
||||
Field string `json:"field"`
|
||||
// Mapping maps from an OIDC group --> Coder organization role
|
||||
Mapping map[string][]string `json:"mapping"`
|
||||
}
|
||||
type RoleSyncSettings codersdk.RoleSyncSettings
|
||||
|
||||
func (s *RoleSyncSettings) Set(v string) error {
|
||||
return json.Unmarshal([]byte(v), s)
|
||||
|
Reference in New Issue
Block a user