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

Commit6254568

Browse files
committed
feat: make OAuth2 provider not enterprise-only
1 parent951dfaa commit6254568

File tree

14 files changed

+92
-161
lines changed

14 files changed

+92
-161
lines changed

‎coderd/coderd.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,34 @@ func New(options *Options) *API {
680680
})
681681
}
682682

683+
// OAuth2 linking routes do not make sense under the /api/v2 path. These are
684+
// for an external application to use Coder as an OAuth2 provider, not for
685+
// logging into Coder with an external OAuth2 provider.
686+
r.Route("/oauth2",func(r chi.Router) {
687+
r.Use(
688+
api.oAuth2ProviderMiddleware,
689+
// Fetch the app as system because in the /tokens route there will be no
690+
// authenticated user.
691+
httpmw.AsAuthzSystem(httpmw.ExtractOAuth2ProviderApp(options.Database)),
692+
)
693+
r.Route("/authorize",func(r chi.Router) {
694+
r.Use(apiKeyMiddlewareRedirect)
695+
r.Get("/",api.getOAuth2ProviderAppAuthorize())
696+
})
697+
r.Route("/tokens",func(r chi.Router) {
698+
r.Group(func(r chi.Router) {
699+
r.Use(apiKeyMiddleware)
700+
// DELETE on /tokens is not part of the OAuth2 spec. It is our own
701+
// route used to revoke permissions from an application. It is here for
702+
// parity with POST on /tokens.
703+
r.Delete("/",api.deleteOAuth2ProviderAppTokens())
704+
})
705+
// The POST /tokens endpoint will be called from an unauthorized client so
706+
// we cannot require an API key.
707+
r.Post("/",api.postOAuth2ProviderAppToken())
708+
})
709+
})
710+
683711
r.Route("/api/v2",func(r chi.Router) {
684712
api.APIHandler=r
685713

@@ -1089,6 +1117,34 @@ func New(options *Options) *API {
10891117
}
10901118
r.Method("GET","/expvar",expvar.Handler())// contains DERP metrics as well as cmdline and memstats
10911119
})
1120+
// Manage OAuth2 applications that can use Coder as an OAuth2 provider.
1121+
r.Route("/oauth2-provider",func(r chi.Router) {
1122+
r.Use(
1123+
apiKeyMiddleware,
1124+
api.oAuth2ProviderMiddleware,
1125+
)
1126+
r.Route("/apps",func(r chi.Router) {
1127+
r.Get("/",api.oAuth2ProviderApps)
1128+
r.Post("/",api.postOAuth2ProviderApp)
1129+
1130+
r.Route("/{app}",func(r chi.Router) {
1131+
r.Use(httpmw.ExtractOAuth2ProviderApp(options.Database))
1132+
r.Get("/",api.oAuth2ProviderApp)
1133+
r.Put("/",api.putOAuth2ProviderApp)
1134+
r.Delete("/",api.deleteOAuth2ProviderApp)
1135+
1136+
r.Route("/secrets",func(r chi.Router) {
1137+
r.Get("/",api.oAuth2ProviderAppSecrets)
1138+
r.Post("/",api.postOAuth2ProviderAppSecret)
1139+
1140+
r.Route("/{secretID}",func(r chi.Router) {
1141+
r.Use(httpmw.ExtractOAuth2ProviderAppSecret(options.Database))
1142+
r.Delete("/",api.deleteOAuth2ProviderAppSecret)
1143+
})
1144+
})
1145+
})
1146+
})
1147+
})
10921148
})
10931149

10941150
ifoptions.SwaggerEndpoint {

‎enterprise/coderd/oauth2.gorenamed to‎coderd/oauth2.go

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ import (
1313
"github.com/coder/coder/v2/coderd/database/dbtime"
1414
"github.com/coder/coder/v2/coderd/httpapi"
1515
"github.com/coder/coder/v2/coderd/httpmw"
16+
"github.com/coder/coder/v2/coderd/identityprovider"
1617
"github.com/coder/coder/v2/codersdk"
17-
"github.com/coder/coder/v2/enterprise/coderd/identityprovider"
1818
)
1919

20-
func (api*API)oAuth2ProviderMiddleware(next http.Handler) http.Handler {
20+
func (*API)oAuth2ProviderMiddleware(next http.Handler) http.Handler {
2121
returnhttp.HandlerFunc(func(rw http.ResponseWriter,r*http.Request) {
2222
if!buildinfo.IsDev() {
2323
httpapi.Write(r.Context(),rw,http.StatusForbidden, codersdk.Response{
@@ -26,17 +26,6 @@ func (api *API) oAuth2ProviderMiddleware(next http.Handler) http.Handler {
2626
return
2727
}
2828

29-
api.entitlementsMu.RLock()
30-
entitled:=api.entitlements.Features[codersdk.FeatureOAuth2Provider].Entitlement!=codersdk.EntitlementNotEntitled
31-
api.entitlementsMu.RUnlock()
32-
33-
if!entitled {
34-
httpapi.Write(r.Context(),rw,http.StatusForbidden, codersdk.Response{
35-
Message:"OAuth2 provider is an Enterprise feature. Contact sales!",
36-
})
37-
return
38-
}
39-
4029
next.ServeHTTP(rw,r)
4130
})
4231
}
@@ -111,7 +100,7 @@ func (api *API) oAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
111100
func (api*API)postOAuth2ProviderApp(rw http.ResponseWriter,r*http.Request) {
112101
var (
113102
ctx=r.Context()
114-
auditor=api.AGPL.Auditor.Load()
103+
auditor=api.Auditor.Load()
115104
aReq,commitAudit=audit.InitRequest[database.OAuth2ProviderApp](rw,&audit.RequestParams{
116105
Audit:*auditor,
117106
Log:api.Logger,
@@ -157,7 +146,7 @@ func (api *API) putOAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
157146
var (
158147
ctx=r.Context()
159148
app=httpmw.OAuth2ProviderApp(r)
160-
auditor=api.AGPL.Auditor.Load()
149+
auditor=api.Auditor.Load()
161150
aReq,commitAudit=audit.InitRequest[database.OAuth2ProviderApp](rw,&audit.RequestParams{
162151
Audit:*auditor,
163152
Log:api.Logger,
@@ -200,7 +189,7 @@ func (api *API) deleteOAuth2ProviderApp(rw http.ResponseWriter, r *http.Request)
200189
var (
201190
ctx=r.Context()
202191
app=httpmw.OAuth2ProviderApp(r)
203-
auditor=api.AGPL.Auditor.Load()
192+
auditor=api.Auditor.Load()
204193
aReq,commitAudit=audit.InitRequest[database.OAuth2ProviderApp](rw,&audit.RequestParams{
205194
Audit:*auditor,
206195
Log:api.Logger,
@@ -263,7 +252,7 @@ func (api *API) postOAuth2ProviderAppSecret(rw http.ResponseWriter, r *http.Requ
263252
var (
264253
ctx=r.Context()
265254
app=httpmw.OAuth2ProviderApp(r)
266-
auditor=api.AGPL.Auditor.Load()
255+
auditor=api.Auditor.Load()
267256
aReq,commitAudit=audit.InitRequest[database.OAuth2ProviderAppSecret](rw,&audit.RequestParams{
268257
Audit:*auditor,
269258
Log:api.Logger,
@@ -317,7 +306,7 @@ func (api *API) deleteOAuth2ProviderAppSecret(rw http.ResponseWriter, r *http.Re
317306
var (
318307
ctx=r.Context()
319308
secret=httpmw.OAuth2ProviderAppSecret(r)
320-
auditor=api.AGPL.Auditor.Load()
309+
auditor=api.Auditor.Load()
321310
aReq,commitAudit=audit.InitRequest[database.OAuth2ProviderAppSecret](rw,&audit.RequestParams{
322311
Audit:*auditor,
323312
Log:api.Logger,

‎enterprise/coderd/oauth2_test.gorenamed to‎coderd/oauth2_test.go

Lines changed: 28 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@ import (
1919
"github.com/coder/coder/v2/coderd/database"
2020
"github.com/coder/coder/v2/coderd/database/dbtestutil"
2121
"github.com/coder/coder/v2/coderd/database/dbtime"
22+
"github.com/coder/coder/v2/coderd/identityprovider"
2223
"github.com/coder/coder/v2/coderd/userpassword"
2324
"github.com/coder/coder/v2/coderd/util/ptr"
2425
"github.com/coder/coder/v2/codersdk"
25-
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
26-
"github.com/coder/coder/v2/enterprise/coderd/identityprovider"
27-
"github.com/coder/coder/v2/enterprise/coderd/license"
2826
"github.com/coder/coder/v2/testutil"
2927
)
3028

@@ -34,11 +32,8 @@ func TestOAuth2ProviderApps(t *testing.T) {
3432
t.Run("Validation",func(t*testing.T) {
3533
t.Parallel()
3634

37-
client,_:=coderdenttest.New(t,&coderdenttest.Options{LicenseOptions:&coderdenttest.LicenseOptions{
38-
Features: license.Features{
39-
codersdk.FeatureOAuth2Provider:1,
40-
},
41-
}})
35+
client:=coderdtest.New(t,nil)
36+
_=coderdtest.CreateFirstUser(t,client)
4237

4338
topCtx:=testutil.Context(t,testutil.WaitLong)
4439

@@ -178,11 +173,8 @@ func TestOAuth2ProviderApps(t *testing.T) {
178173
t.Run("DeleteNonExisting",func(t*testing.T) {
179174
t.Parallel()
180175

181-
client,owner:=coderdenttest.New(t,&coderdenttest.Options{LicenseOptions:&coderdenttest.LicenseOptions{
182-
Features: license.Features{
183-
codersdk.FeatureOAuth2Provider:1,
184-
},
185-
}})
176+
client:=coderdtest.New(t,nil)
177+
owner:=coderdtest.CreateFirstUser(t,client)
186178
another,_:=coderdtest.CreateAnotherUser(t,client,owner.OrganizationID)
187179

188180
ctx:=testutil.Context(t,testutil.WaitLong)
@@ -194,11 +186,8 @@ func TestOAuth2ProviderApps(t *testing.T) {
194186
t.Run("OK",func(t*testing.T) {
195187
t.Parallel()
196188

197-
client,owner:=coderdenttest.New(t,&coderdenttest.Options{LicenseOptions:&coderdenttest.LicenseOptions{
198-
Features: license.Features{
199-
codersdk.FeatureOAuth2Provider:1,
200-
},
201-
}})
189+
client:=coderdtest.New(t,nil)
190+
owner:=coderdtest.CreateFirstUser(t,client)
202191
another,_:=coderdtest.CreateAnotherUser(t,client,owner.OrganizationID)
203192

204193
ctx:=testutil.Context(t,testutil.WaitLong)
@@ -269,11 +258,8 @@ func TestOAuth2ProviderApps(t *testing.T) {
269258

270259
t.Run("ByUser",func(t*testing.T) {
271260
t.Parallel()
272-
client,owner:=coderdenttest.New(t,&coderdenttest.Options{LicenseOptions:&coderdenttest.LicenseOptions{
273-
Features: license.Features{
274-
codersdk.FeatureOAuth2Provider:1,
275-
},
276-
}})
261+
client:=coderdtest.New(t,nil)
262+
owner:=coderdtest.CreateFirstUser(t,client)
277263
another,user:=coderdtest.CreateAnotherUser(t,client,owner.OrganizationID)
278264
ctx:=testutil.Context(t,testutil.WaitLong)
279265
_=generateApps(ctx,t,client,"by-user")
@@ -288,11 +274,8 @@ func TestOAuth2ProviderApps(t *testing.T) {
288274
funcTestOAuth2ProviderAppSecrets(t*testing.T) {
289275
t.Parallel()
290276

291-
client,_:=coderdenttest.New(t,&coderdenttest.Options{LicenseOptions:&coderdenttest.LicenseOptions{
292-
Features: license.Features{
293-
codersdk.FeatureOAuth2Provider:1,
294-
},
295-
}})
277+
client:=coderdtest.New(t,nil)
278+
_=coderdtest.CreateFirstUser(t,client)
296279

297280
topCtx:=testutil.Context(t,testutil.WaitLong)
298281

@@ -383,17 +366,11 @@ func TestOAuth2ProviderTokenExchange(t *testing.T) {
383366
t.Parallel()
384367

385368
db,pubsub:=dbtestutil.NewDB(t)
386-
ownerClient,owner:=coderdenttest.New(t,&coderdenttest.Options{
387-
Options:&coderdtest.Options{
388-
Database:db,
389-
Pubsub:pubsub,
390-
},
391-
LicenseOptions:&coderdenttest.LicenseOptions{
392-
Features: license.Features{
393-
codersdk.FeatureOAuth2Provider:1,
394-
},
395-
},
369+
ownerClient:=coderdtest.New(t,&coderdtest.Options{
370+
Database:db,
371+
Pubsub:pubsub,
396372
})
373+
owner:=coderdtest.CreateFirstUser(t,ownerClient)
397374
topCtx:=testutil.Context(t,testutil.WaitLong)
398375
apps:=generateApps(topCtx,t,ownerClient,"token-exchange")
399376

@@ -764,17 +741,11 @@ func TestOAuth2ProviderTokenRefresh(t *testing.T) {
764741
topCtx:=testutil.Context(t,testutil.WaitLong)
765742

766743
db,pubsub:=dbtestutil.NewDB(t)
767-
ownerClient,owner:=coderdenttest.New(t,&coderdenttest.Options{
768-
Options:&coderdtest.Options{
769-
Database:db,
770-
Pubsub:pubsub,
771-
},
772-
LicenseOptions:&coderdenttest.LicenseOptions{
773-
Features: license.Features{
774-
codersdk.FeatureOAuth2Provider:1,
775-
},
776-
},
744+
ownerClient:=coderdtest.New(t,&coderdtest.Options{
745+
Database:db,
746+
Pubsub:pubsub,
777747
})
748+
owner:=coderdtest.CreateFirstUser(t,ownerClient)
778749
apps:=generateApps(topCtx,t,ownerClient,"token-refresh")
779750

780751
//nolint:gocritic // OAauth2 app management requires owner permission.
@@ -935,11 +906,8 @@ type exchangeSetup struct {
935906
funcTestOAuth2ProviderRevoke(t*testing.T) {
936907
t.Parallel()
937908

938-
client,owner:=coderdenttest.New(t,&coderdenttest.Options{LicenseOptions:&coderdenttest.LicenseOptions{
939-
Features: license.Features{
940-
codersdk.FeatureOAuth2Provider:1,
941-
},
942-
}})
909+
client:=coderdtest.New(t,nil)
910+
owner:=coderdtest.CreateFirstUser(t,client)
943911

944912
tests:= []struct {
945913
namestring
@@ -1138,3 +1106,10 @@ func authorizationFlow(ctx context.Context, client *codersdk.Client, cfg *oauth2
11381106
},
11391107
)
11401108
}
1109+
1110+
funcmust[Tany](valueT,errerror)T {
1111+
iferr!=nil {
1112+
panic(err)
1113+
}
1114+
returnvalue
1115+
}

‎codersdk/deployment.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ const (
5353
FeatureExternalTokenEncryptionFeatureName="external_token_encryption"
5454
FeatureWorkspaceBatchActionsFeatureName="workspace_batch_actions"
5555
FeatureAccessControlFeatureName="access_control"
56-
FeatureOAuth2ProviderFeatureName="oauth2_provider"
5756
FeatureControlSharedPortsFeatureName="control_shared_ports"
5857
)
5958

@@ -74,7 +73,6 @@ var FeatureNames = []FeatureName{
7473
FeatureExternalTokenEncryption,
7574
FeatureWorkspaceBatchActions,
7675
FeatureAccessControl,
77-
FeatureOAuth2Provider,
7876
FeatureControlSharedPorts,
7977
}
8078

@@ -85,8 +83,6 @@ func (n FeatureName) Humanize() string {
8583
return"Template RBAC"
8684
caseFeatureSCIM:
8785
return"SCIM"
88-
caseFeatureOAuth2Provider:
89-
return"OAuth Provider"
9086
default:
9187
returnstrings.Title(strings.ReplaceAll(string(n),"_"," "))
9288
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp