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

Commit00860cf

Browse files
authored
feat: add group mapping option for group sync (#6705)
* feat: add group mapping option for group sync* fixup! feat: add group mapping option for group sync
1 parent120bc4b commit00860cf

File tree

12 files changed

+114
-18
lines changed

12 files changed

+114
-18
lines changed

‎cli/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,7 @@ flags, and YAML configuration. The precedence is as follows:
796796
AllowSignups:cfg.OIDC.AllowSignups.Value(),
797797
UsernameField:cfg.OIDC.UsernameField.String(),
798798
GroupField:cfg.OIDC.GroupField.String(),
799+
GroupMapping:cfg.OIDC.GroupMapping.Value,
799800
SignInText:cfg.OIDC.SignInText.String(),
800801
IconURL:cfg.OIDC.IconURL.String(),
801802
IgnoreEmailVerified:cfg.OIDC.IgnoreEmailVerified.Value(),

‎coderd/apidoc/docs.go

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/apidoc/swagger.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/coderd.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,12 @@ func New(options *Options) *API {
223223
options.SSHConfig.HostnamePrefix="coder."
224224
}
225225
ifoptions.SetUserGroups==nil {
226-
options.SetUserGroups=func(context.Context, database.Store, uuid.UUID, []string)error {returnnil }
226+
options.SetUserGroups=func(ctx context.Context,_ database.Store,id uuid.UUID,groups []string)error {
227+
options.Logger.Warn(ctx,"attempted to assign OIDC groups without enterprise license",
228+
slog.F("id",id),slog.F("groups",groups),
229+
)
230+
returnnil
231+
}
227232
}
228233
ifoptions.TemplateScheduleStore==nil {
229234
options.TemplateScheduleStore=schedule.NewAGPLTemplateScheduleStore()

‎coderd/userauth.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,10 @@ type OIDCConfig struct {
481481
// groups. If the group field is the empty string, then no group updates
482482
// will ever come from the OIDC provider.
483483
GroupFieldstring
484+
// GroupMapping controls how groups returned by the OIDC provider get mapped
485+
// to groups within Coder.
486+
// map[oidcGroupName]coderGroupName
487+
GroupMappingmap[string]string
484488
// SignInText is the text to display on the OIDC login button
485489
SignInTextstring
486490
// IconURL points to the URL of an icon to display on the OIDC login button
@@ -651,6 +655,11 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) {
651655
})
652656
return
653657
}
658+
659+
ifmappedGroup,ok:=api.OIDCConfig.GroupMapping[group];ok {
660+
group=mappedGroup
661+
}
662+
654663
groups=append(groups,group)
655664
}
656665
}else {

‎codersdk/deployment.go

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"encoding/json"
66
"flag"
7-
"fmt"
87
"math"
98
"net/http"
109
"os"
@@ -199,7 +198,7 @@ func ParseSSHConfigOption(opt string) (key string, value string, err error) {
199198
returnr==' '||r=='='
200199
})
201200
ifidx==-1 {
202-
return"","",fmt.Errorf("invalid config-ssh option %q",opt)
201+
return"","",xerrors.Errorf("invalid config-ssh option %q",opt)
203202
}
204203
returnopt[:idx],opt[idx+1:],nil
205204
}
@@ -248,17 +247,18 @@ type OAuth2GithubConfig struct {
248247
}
249248

250249
typeOIDCConfigstruct {
251-
AllowSignups clibase.Bool`json:"allow_signups" typescript:",notnull"`
252-
ClientID clibase.String`json:"client_id" typescript:",notnull"`
253-
ClientSecret clibase.String`json:"client_secret" typescript:",notnull"`
254-
EmailDomain clibase.Strings`json:"email_domain" typescript:",notnull"`
255-
IssuerURL clibase.String`json:"issuer_url" typescript:",notnull"`
256-
Scopes clibase.Strings`json:"scopes" typescript:",notnull"`
257-
IgnoreEmailVerified clibase.Bool`json:"ignore_email_verified" typescript:",notnull"`
258-
UsernameField clibase.String`json:"username_field" typescript:",notnull"`
259-
GroupField clibase.String`json:"groups_field" typescript:",notnull"`
260-
SignInText clibase.String`json:"sign_in_text" typescript:",notnull"`
261-
IconURL clibase.URL`json:"icon_url" typescript:",notnull"`
250+
AllowSignups clibase.Bool`json:"allow_signups" typescript:",notnull"`
251+
ClientID clibase.String`json:"client_id" typescript:",notnull"`
252+
ClientSecret clibase.String`json:"client_secret" typescript:",notnull"`
253+
EmailDomain clibase.Strings`json:"email_domain" typescript:",notnull"`
254+
IssuerURL clibase.String`json:"issuer_url" typescript:",notnull"`
255+
Scopes clibase.Strings`json:"scopes" typescript:",notnull"`
256+
IgnoreEmailVerified clibase.Bool`json:"ignore_email_verified" typescript:",notnull"`
257+
UsernameField clibase.String`json:"username_field" typescript:",notnull"`
258+
GroupField clibase.String`json:"groups_field" typescript:",notnull"`
259+
GroupMapping clibase.Struct[map[string]string]`json:"group_mapping" typescript:",notnull"`
260+
SignInText clibase.String`json:"sign_in_text" typescript:",notnull"`
261+
IconURL clibase.URL`json:"icon_url" typescript:",notnull"`
262262
}
263263

264264
typeTelemetryConfigstruct {
@@ -875,6 +875,16 @@ when required by your organization's security policy.`,
875875
Group:&deploymentGroupOIDC,
876876
YAML:"groupField",
877877
},
878+
{
879+
Name:"OIDC Group Mapping",
880+
Description:"A map of OIDC group IDs and the group in Coder it should map to. This is useful for when OIDC providers only return group IDs.",
881+
Flag:"oidc-group-mapping",
882+
Env:"OIDC_GROUP_MAPPING",
883+
Default:"{}",
884+
Value:&c.OIDC.GroupMapping,
885+
Group:&deploymentGroupOIDC,
886+
YAML:"groupMapping",
887+
},
878888
{
879889
Name:"OpenID Connect sign in text",
880890
Description:"The text to show on the OpenID Connect sign in button",

‎docs/admin/auth.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,4 +197,20 @@ CODER_OIDC_SCOPES=openid,profile,email,groups
197197
On login, users will automatically be assigned to groups that have matching
198198
names in Coder and removed from groups that the user no longer belongs to.
199199

200+
For cases when an OIDC provider only returns group IDs ([Azure AD][azure-gids])
201+
or you want to have different group names in Coder than in your OIDC provider,
202+
you can configure mapping between the two.
203+
204+
```console
205+
#as an environment variable
206+
CODER_OIDC_GROUP_MAPPING='{"myOIDCGroupID": "myCoderGroupName"}'
207+
#as a flag
208+
--oidc-group-mapping '{"myOIDCGroupID": "myCoderGroupName"}'
209+
```
210+
211+
From the example above, users that belong to the`myOIDCGroupID` group in your
212+
OIDC provider will be added to the`myCoderGroupName` group in Coder.
213+
200214
>**Note:** Groups are only updated on login.
215+
216+
[azure-gids]:https://github.com/MicrosoftDocs/azure-docs/issues/59766#issuecomment-664387195

‎docs/api/general.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \
234234
"client_id":"string",
235235
"client_secret":"string",
236236
"email_domain": ["string"],
237+
"group_mapping": {},
237238
"groups_field":"string",
238239
"icon_url": {
239240
"forceQuery":true,

‎docs/api/schemas.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1766,6 +1766,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a
17661766
"client_id":"string",
17671767
"client_secret":"string",
17681768
"email_domain": ["string"],
1769+
"group_mapping": {},
17691770
"groups_field":"string",
17701771
"icon_url": {
17711772
"forceQuery":true,
@@ -2110,6 +2111,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a
21102111
"client_id":"string",
21112112
"client_secret":"string",
21122113
"email_domain": ["string"],
2114+
"group_mapping": {},
21132115
"groups_field":"string",
21142116
"icon_url": {
21152117
"forceQuery":true,
@@ -2771,6 +2773,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a
27712773
"client_id":"string",
27722774
"client_secret":"string",
27732775
"email_domain": ["string"],
2776+
"group_mapping": {},
27742777
"groups_field":"string",
27752778
"icon_url": {
27762779
"forceQuery":true,
@@ -2801,6 +2804,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a
28012804
|`client_id`| string| false|||
28022805
|`client_secret`| string| false|||
28032806
|`email_domain`| array of string| false|||
2807+
|`group_mapping`| object| false|||
28042808
|`groups_field`| string| false|||
28052809
|`icon_url`|[clibase.URL](#clibaseurl)| false|||
28062810
|`ignore_email_verified`| boolean| false|||

‎enterprise/coderd/userauth_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,51 @@ func TestUserOIDC(t *testing.T) {
6767
require.NoError(t,err)
6868
require.Len(t,group.Members,1)
6969
})
70+
t.Run("AssignsMapped",func(t*testing.T) {
71+
t.Parallel()
72+
73+
ctx,_:=testutil.Context(t)
74+
conf:=coderdtest.NewOIDCConfig(t,"")
75+
76+
oidcGroupName:="pingpong"
77+
coderGroupName:="bingbong"
78+
79+
config:=conf.OIDCConfig(t, jwt.MapClaims{},func(cfg*coderd.OIDCConfig) {
80+
cfg.GroupMapping=map[string]string{oidcGroupName:coderGroupName}
81+
})
82+
config.AllowSignups=true
83+
84+
client:=coderdenttest.New(t,&coderdenttest.Options{
85+
Options:&coderdtest.Options{
86+
OIDCConfig:config,
87+
},
88+
})
89+
_=coderdtest.CreateFirstUser(t,client)
90+
coderdenttest.AddLicense(t,client, coderdenttest.LicenseOptions{
91+
AllFeatures:true,
92+
})
93+
94+
admin,err:=client.User(ctx,"me")
95+
require.NoError(t,err)
96+
require.Len(t,admin.OrganizationIDs,1)
97+
98+
group,err:=client.CreateGroup(ctx,admin.OrganizationIDs[0], codersdk.CreateGroupRequest{
99+
Name:coderGroupName,
100+
})
101+
require.NoError(t,err)
102+
require.Len(t,group.Members,0)
103+
104+
resp:=oidcCallback(t,client,conf.EncodeClaims(t, jwt.MapClaims{
105+
"email":"colin@coder.com",
106+
"groups": []string{oidcGroupName},
107+
}))
108+
assert.Equal(t,http.StatusTemporaryRedirect,resp.StatusCode)
109+
110+
group,err=client.Group(ctx,group.ID)
111+
require.NoError(t,err)
112+
require.Len(t,group.Members,1)
113+
})
114+
70115
t.Run("AddThenRemove",func(t*testing.T) {
71116
t.Parallel()
72117

‎go.sum

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -376,10 +376,6 @@ github.com/coder/retry v1.3.1-0.20230210155434-e90a2e1e091d h1:09JG37IgTB6n3ouX9
376376
github.com/coder/retryv1.3.1-0.20230210155434-e90a2e1e091d/go.mod h1:r+1J5i/989wt6CUeNSuvFKKA9hHuKKPMxdzDbTuvwwk=
377377
github.com/coder/sshv0.0.0-20220811105153-fcea99919338 h1:tN5GKFT68YLVzJoA8AHuiMNJ0qlhoD3pGN3JY9gxSko=
378378
github.com/coder/sshv0.0.0-20220811105153-fcea99919338/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
379-
github.com/coder/tailscalev1.1.1-0.20230314023417-d9efcc0ac972 h1:193YGsJz8hc4yxqAclE36paKl+9CQ6KGLgdleIguCVE=
380-
github.com/coder/tailscalev1.1.1-0.20230314023417-d9efcc0ac972/go.mod h1:jpg+77g19FpXL43U1VoIqoSg1K/Vh5CVxycGldQ8KhA=
381-
github.com/coder/tailscalev1.1.1-0.20230321164649-3362540e3026 h1:6YnWw08eQEGc/7KyweGWP8urOb9TDlo6S35ZqNm8qsQ=
382-
github.com/coder/tailscalev1.1.1-0.20230321164649-3362540e3026/go.mod h1:jpg+77g19FpXL43U1VoIqoSg1K/Vh5CVxycGldQ8KhA=
383379
github.com/coder/tailscalev1.1.1-0.20230321171725-fed359a0cafa h1:EjRGgTz7BUECmbV8jHTi1/rKdDjJESGSlm1Jp7evvCQ=
384380
github.com/coder/tailscalev1.1.1-0.20230321171725-fed359a0cafa/go.mod h1:jpg+77g19FpXL43U1VoIqoSg1K/Vh5CVxycGldQ8KhA=
385381
github.com/coder/terraform-provider-coderv0.6.20 h1:bVyITX9JlbnGzKzTj0qi/JziUCGqD2DiN3cXaWyDcxE=

‎site/src/api/typesGenerated.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,9 @@ export interface OIDCConfig {
507507
readonlyignore_email_verified:boolean
508508
readonlyusername_field:string
509509
readonlygroups_field:string
510+
// Named type "github.com/coder/coder/cli/clibase.Struct[map[string]string]" unknown, using "any"
511+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type
512+
readonlygroup_mapping:any
510513
readonlysign_in_text:string
511514
readonlyicon_url:string
512515
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp