Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitff1eabe

Browse files
coadlerEmyrk
andauthored
feat: add SCIM support for multi-organization (#14691)
* chore: use legacy "AssignDefault" option for legacy behavior in SCIM (#14696)* chore: reference legacy assign default option for legacy behaviorAssignDefault is a boolean flag mainly for single org and legacydeployments. Use this flag to determine SCIM behavior.---------Co-authored-by: Steven Masley <Emyrk@users.noreply.github.com>
1 parent7139374 commitff1eabe

File tree

4 files changed

+79
-9
lines changed

4 files changed

+79
-9
lines changed

‎coderd/idpsync/idpsync.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
// claims to the internal representation of a user in Coder.
2525
// TODO: Move group + role sync into this interface.
2626
typeIDPSyncinterface {
27+
AssignDefaultOrganization()bool
2728
OrganizationSyncEnabled()bool
2829
// ParseOrganizationClaims takes claims from an OIDC provider, and returns the
2930
// organization sync params for assigning users into organizations.

‎coderd/idpsync/organization.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ func (AGPLIDPSync) OrganizationSyncEnabled() bool {
3232
returnfalse
3333
}
3434

35+
func (sAGPLIDPSync)AssignDefaultOrganization()bool {
36+
returns.OrganizationAssignDefault
37+
}
38+
3539
func (sAGPLIDPSync)ParseOrganizationClaims(_ context.Context,_ jwt.MapClaims) (OrganizationParams,*HTTPError) {
3640
// For AGPL we only sync the default organization.
3741
returnOrganizationParams{

‎enterprise/coderd/scim.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -217,22 +217,27 @@ func (api *API) scimPostUser(rw http.ResponseWriter, r *http.Request) {
217217
sUser.UserName=codersdk.UsernameFrom(sUser.UserName)
218218
}
219219

220-
// TODO: This is a temporary solution that does not support multi-org
221-
// deployments. This assumption places all new SCIM users into the
222-
//default organization.
223-
//nolint:gocritic
224-
defaultOrganization,err:=api.Database.GetDefaultOrganization(dbauthz.AsSystemRestricted(ctx))
225-
iferr!=nil {
226-
_=handlerutil.WriteError(rw,err)
227-
return
220+
// If organization sync is enabled, the user's organizations will be
221+
// corrected on login. If including the default org, then always assign
222+
// the default org, regardless if sync is enabled or not.
223+
// This is to preserve single org deployment behavior.
224+
organizations:= []uuid.UUID{}
225+
ifapi.IDPSync.AssignDefaultOrganization() {
226+
//nolint:gocritic // SCIM operations are a system user
227+
defaultOrganization,err:=api.Database.GetDefaultOrganization(dbauthz.AsSystemRestricted(ctx))
228+
iferr!=nil {
229+
_=handlerutil.WriteError(rw,err)
230+
return
231+
}
232+
organizations=append(organizations,defaultOrganization.ID)
228233
}
229234

230235
//nolint:gocritic // needed for SCIM
231236
dbUser,err=api.AGPL.CreateUser(dbauthz.AsSystemRestricted(ctx),api.Database, agpl.CreateUserRequest{
232237
CreateUserRequestWithOrgs: codersdk.CreateUserRequestWithOrgs{
233238
Username:sUser.UserName,
234239
Email:email,
235-
OrganizationIDs:[]uuid.UUID{defaultOrganization.ID},
240+
OrganizationIDs:organizations,
236241
},
237242
LoginType:database.LoginTypeOIDC,
238243
// Do not send notifications to user admins as SCIM endpoint might be called sequentially to all users.

‎enterprise/coderd/scim_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,66 @@ func TestScim(t *testing.T) {
157157
require.Len(t,userRes.Users,1)
158158
assert.Equal(t,sUser.Emails[0].Value,userRes.Users[0].Email)
159159
assert.Equal(t,sUser.UserName,userRes.Users[0].Username)
160+
assert.Len(t,userRes.Users[0].OrganizationIDs,1)
161+
162+
// Expect zero notifications (SkipNotifications = true)
163+
require.Empty(t,notifyEnq.Sent)
164+
})
165+
166+
t.Run("OKNoDefault",func(t*testing.T) {
167+
t.Parallel()
168+
169+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
170+
defercancel()
171+
172+
// given
173+
scimAPIKey:= []byte("hi")
174+
mockAudit:=audit.NewMock()
175+
notifyEnq:=&testutil.FakeNotificationsEnqueuer{}
176+
dv:=coderdtest.DeploymentValues(t)
177+
dv.OIDC.OrganizationAssignDefault=false
178+
client,_:=coderdenttest.New(t,&coderdenttest.Options{
179+
Options:&coderdtest.Options{
180+
Auditor:mockAudit,
181+
NotificationsEnqueuer:notifyEnq,
182+
DeploymentValues:dv,
183+
},
184+
SCIMAPIKey:scimAPIKey,
185+
AuditLogging:true,
186+
LicenseOptions:&coderdenttest.LicenseOptions{
187+
AccountID:"coolin",
188+
Features: license.Features{
189+
codersdk.FeatureSCIM:1,
190+
codersdk.FeatureAuditLog:1,
191+
},
192+
},
193+
})
194+
mockAudit.ResetLogs()
195+
196+
// when
197+
sUser:=makeScimUser(t)
198+
res,err:=client.Request(ctx,"POST","/scim/v2/Users",sUser,setScimAuth(scimAPIKey))
199+
require.NoError(t,err)
200+
deferres.Body.Close()
201+
require.Equal(t,http.StatusOK,res.StatusCode)
202+
203+
// then
204+
// Expect audit logs
205+
aLogs:=mockAudit.AuditLogs()
206+
require.Len(t,aLogs,1)
207+
af:=map[string]string{}
208+
err=json.Unmarshal([]byte(aLogs[0].AdditionalFields),&af)
209+
require.NoError(t,err)
210+
assert.Equal(t,coderd.SCIMAuditAdditionalFields,af)
211+
assert.Equal(t,database.AuditActionCreate,aLogs[0].Action)
212+
213+
// Expect users exposed over API
214+
userRes,err:=client.Users(ctx, codersdk.UsersRequest{Search:sUser.Emails[0].Value})
215+
require.NoError(t,err)
216+
require.Len(t,userRes.Users,1)
217+
assert.Equal(t,sUser.Emails[0].Value,userRes.Users[0].Email)
218+
assert.Equal(t,sUser.UserName,userRes.Users[0].Username)
219+
assert.Len(t,userRes.Users[0].OrganizationIDs,0)
160220

161221
// Expect zero notifications (SkipNotifications = true)
162222
require.Empty(t,notifyEnq.Sent)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp