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

Commit760c4a8

Browse files
committed
feat: addowner_oidc_access_token tocoder_workspace data source
See the discussion in Discord here:https://discord.com/channels/747933592273027093/1071182088490987542/1071182088490987542Related provider PR:coder/terraform-provider-coder#91
1 parentf096915 commit760c4a8

File tree

6 files changed

+270
-106
lines changed

6 files changed

+270
-106
lines changed

‎coderd/provisionerdserver/provisionerdserver.go

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ import (
1818
"github.com/tabbed/pqtype"
1919
"golang.org/x/exp/maps"
2020
"golang.org/x/exp/slices"
21+
"golang.org/x/oauth2"
2122
"golang.org/x/xerrors"
2223
protobuf"google.golang.org/protobuf/proto"
2324

2425
"cdr.dev/slog"
2526

2627
"github.com/coder/coder/coderd/audit"
2728
"github.com/coder/coder/coderd/database"
29+
"github.com/coder/coder/coderd/httpmw"
2830
"github.com/coder/coder/coderd/parameter"
2931
"github.com/coder/coder/coderd/telemetry"
3032
"github.com/coder/coder/codersdk"
@@ -52,6 +54,7 @@ type Server struct {
5254
Auditor*atomic.Pointer[audit.Auditor]
5355

5456
AcquireJobDebounce time.Duration
57+
OIDCConfig httpmw.OAuth2Config
5558
}
5659

5760
// AcquireJob queries the database to lock a job.
@@ -155,6 +158,14 @@ func (server *Server) AcquireJob(ctx context.Context, _ *proto.Empty) (*proto.Ac
155158
returnnil,failJob(fmt.Sprintf("publish workspace update: %s",err))
156159
}
157160

161+
varworkspaceOwnerOIDCAccessTokenstring
162+
ifserver.OIDCConfig!=nil {
163+
workspaceOwnerOIDCAccessToken,err=obtainOIDCAccessToken(ctx,server.Database,server.OIDCConfig,owner.ID)
164+
iferr!=nil {
165+
returnnil,failJob(fmt.Sprintf("obtain OIDC access token: %s",err))
166+
}
167+
}
168+
158169
// Compute parameters for the workspace to consume.
159170
parameters,err:=parameter.Compute(ctx,server.Database, parameter.ComputeScope{
160171
TemplateImportJobID:templateVersion.JobID,
@@ -194,13 +205,14 @@ func (server *Server) AcquireJob(ctx context.Context, _ *proto.Empty) (*proto.Ac
194205
ParameterValues:protoParameters,
195206
RichParameterValues:convertRichParameterValues(workspaceBuildParameters),
196207
Metadata:&sdkproto.Provision_Metadata{
197-
CoderUrl:server.AccessURL.String(),
198-
WorkspaceTransition:transition,
199-
WorkspaceName:workspace.Name,
200-
WorkspaceOwner:owner.Username,
201-
WorkspaceOwnerEmail:owner.Email,
202-
WorkspaceId:workspace.ID.String(),
203-
WorkspaceOwnerId:owner.ID.String(),
208+
CoderUrl:server.AccessURL.String(),
209+
WorkspaceTransition:transition,
210+
WorkspaceName:workspace.Name,
211+
WorkspaceOwner:owner.Username,
212+
WorkspaceOwnerEmail:owner.Email,
213+
WorkspaceOwnerOidcAccessToken:workspaceOwnerOIDCAccessToken,
214+
WorkspaceId:workspace.ID.String(),
215+
WorkspaceOwnerId:owner.ID.String(),
204216
},
205217
},
206218
}
@@ -1062,6 +1074,51 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
10621074
returnnil
10631075
}
10641076

1077+
// obtainOIDCAccessToken returns a valid OpenID Connect access token
1078+
// for the user if it's able to obtain one, otherwise it returns an empty string.
1079+
funcobtainOIDCAccessToken(ctx context.Context,db database.Store,oidcConfig httpmw.OAuth2Config,userID uuid.UUID) (string,error) {
1080+
link,err:=db.GetUserLinkByUserIDLoginType(ctx, database.GetUserLinkByUserIDLoginTypeParams{
1081+
UserID:userID,
1082+
LoginType:database.LoginTypeOIDC,
1083+
})
1084+
iferrors.Is(err,sql.ErrNoRows) {
1085+
err=nil
1086+
}
1087+
iferr!=nil {
1088+
return"",xerrors.Errorf("get owner oidc link: %w",err)
1089+
}
1090+
1091+
iflink.OAuthExpiry.Before(database.Now())&&!link.OAuthExpiry.IsZero()&&link.OAuthRefreshToken!="" {
1092+
token,err:=oidcConfig.TokenSource(ctx,&oauth2.Token{
1093+
AccessToken:link.OAuthAccessToken,
1094+
RefreshToken:link.OAuthRefreshToken,
1095+
Expiry:link.OAuthExpiry,
1096+
}).Token()
1097+
iferr!=nil {
1098+
// If OIDC fails to refresh, we return an empty string and don't fail.
1099+
// There isn't a way to hard-opt in to OIDC from a template, so we don't
1100+
// want to fail builds if users haven't authenticated for a while or something.
1101+
return"",nil
1102+
}
1103+
link.OAuthAccessToken=token.AccessToken
1104+
link.OAuthRefreshToken=token.RefreshToken
1105+
link.OAuthExpiry=token.Expiry
1106+
1107+
link,err=db.UpdateUserLink(ctx, database.UpdateUserLinkParams{
1108+
UserID:userID,
1109+
LoginType:database.LoginTypeOIDC,
1110+
OAuthAccessToken:link.OAuthAccessToken,
1111+
OAuthRefreshToken:link.OAuthRefreshToken,
1112+
OAuthExpiry:link.OAuthExpiry,
1113+
})
1114+
iferr!=nil {
1115+
return"",xerrors.Errorf("update user link: %w",err)
1116+
}
1117+
}
1118+
1119+
returnlink.OAuthAccessToken,nil
1120+
}
1121+
10651122
funcconvertValidationTypeSystem(typeSystem sdkproto.ParameterSchema_TypeSystem) (database.ParameterTypeSystem,error) {
10661123
switchtypeSystem {
10671124
casesdkproto.ParameterSchema_None:
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package provisionerdserver
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
8+
"github.com/coder/coder/coderd/database"
9+
"github.com/coder/coder/coderd/database/dbfake"
10+
"github.com/coder/coder/coderd/database/dbgen"
11+
"github.com/google/uuid"
12+
"github.com/stretchr/testify/require"
13+
"golang.org/x/oauth2"
14+
)
15+
16+
funcTestObtainOIDCAccessToken(t*testing.T) {
17+
t.Parallel()
18+
ctx:=context.Background()
19+
t.Run("NoToken",func(t*testing.T) {
20+
t.Parallel()
21+
db:=dbfake.New()
22+
_,err:=obtainOIDCAccessToken(ctx,db,nil,uuid.Nil)
23+
require.NoError(t,err)
24+
})
25+
t.Run("InvalidConfig",func(t*testing.T) {
26+
// We still want OIDC to succeed even if exchanging the token fails.
27+
t.Parallel()
28+
db:=dbfake.New()
29+
user:=dbgen.User(t,db, database.User{})
30+
dbgen.UserLink(t,db, database.UserLink{
31+
UserID:user.ID,
32+
LoginType:database.LoginTypeOIDC,
33+
OAuthExpiry:database.Now().Add(-time.Hour),
34+
})
35+
_,err:=obtainOIDCAccessToken(ctx,db,&oauth2.Config{},user.ID)
36+
require.NoError(t,err)
37+
})
38+
t.Run("Exchange",func(t*testing.T) {
39+
t.Parallel()
40+
db:=dbfake.New()
41+
user:=dbgen.User(t,db, database.User{})
42+
dbgen.UserLink(t,db, database.UserLink{
43+
UserID:user.ID,
44+
LoginType:database.LoginTypeOIDC,
45+
OAuthExpiry:database.Now().Add(-time.Hour),
46+
})
47+
_,err:=obtainOIDCAccessToken(ctx,db,&oauth2Config{
48+
tokenSource:func() (*oauth2.Token,error) {
49+
return&oauth2.Token{
50+
AccessToken:"token",
51+
},nil
52+
},
53+
},user.ID)
54+
require.NoError(t,err)
55+
link,err:=db.GetUserLinkByUserIDLoginType(ctx, database.GetUserLinkByUserIDLoginTypeParams{
56+
UserID:user.ID,
57+
LoginType:database.LoginTypeOIDC,
58+
})
59+
require.NoError(t,err)
60+
require.Equal(t,"token",link.OAuthAccessToken)
61+
})
62+
}
63+
64+
typeoauth2Configstruct {
65+
tokenSourceoauth2TokenSource
66+
}
67+
68+
func (o*oauth2Config)TokenSource(context.Context,*oauth2.Token) oauth2.TokenSource {
69+
returno.tokenSource
70+
}
71+
72+
func (*oauth2Config)AuthCodeURL(string,...oauth2.AuthCodeOption)string {
73+
return""
74+
}
75+
76+
func (*oauth2Config)Exchange(context.Context,string,...oauth2.AuthCodeOption) (*oauth2.Token,error) {
77+
return&oauth2.Token{},nil
78+
}
79+
80+
typeoauth2TokenSourcefunc() (*oauth2.Token,error)
81+
82+
func (ooauth2TokenSource)Token() (*oauth2.Token,error) {
83+
returno()
84+
}

‎coderd/provisionerdserver/provisionerdserver_test.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/google/uuid"
1313
"github.com/stretchr/testify/require"
14+
"golang.org/x/oauth2"
1415

1516
"cdr.dev/slog/sloggers/slogtest"
1617
"github.com/coder/coder/coderd/audit"
@@ -90,6 +91,12 @@ func TestAcquireJob(t *testing.T) {
9091
ctx:=context.Background()
9192

9293
user:=dbgen.User(t,srv.Database, database.User{})
94+
link:=dbgen.UserLink(t,srv.Database, database.UserLink{
95+
LoginType:database.LoginTypeOIDC,
96+
UserID:user.ID,
97+
OAuthExpiry:database.Now().Add(time.Hour),
98+
OAuthAccessToken:"access-token",
99+
})
93100
template:=dbgen.Template(t,srv.Database, database.Template{
94101
Name:"template",
95102
Provisioner:database.ProvisionerTypeEcho,
@@ -169,13 +176,14 @@ func TestAcquireJob(t *testing.T) {
169176
WorkspaceName:workspace.Name,
170177
ParameterValues: []*sdkproto.ParameterValue{},
171178
Metadata:&sdkproto.Provision_Metadata{
172-
CoderUrl:srv.AccessURL.String(),
173-
WorkspaceTransition:sdkproto.WorkspaceTransition_START,
174-
WorkspaceName:workspace.Name,
175-
WorkspaceOwner:user.Username,
176-
WorkspaceOwnerEmail:user.Email,
177-
WorkspaceId:workspace.ID.String(),
178-
WorkspaceOwnerId:user.ID.String(),
179+
CoderUrl:srv.AccessURL.String(),
180+
WorkspaceTransition:sdkproto.WorkspaceTransition_START,
181+
WorkspaceName:workspace.Name,
182+
WorkspaceOwner:user.Username,
183+
WorkspaceOwnerEmail:user.Email,
184+
WorkspaceId:workspace.ID.String(),
185+
WorkspaceOwnerId:user.ID.String(),
186+
WorkspaceOwnerOidcAccessToken:link.OAuthAccessToken,
179187
},
180188
},
181189
})
@@ -804,6 +812,7 @@ func setup(t *testing.T, ignoreLogErrors bool) *provisionerdserver.Server {
804812
return&provisionerdserver.Server{
805813
ID:uuid.New(),
806814
Logger:slogtest.Make(t,&slogtest.Options{IgnoreErrors:ignoreLogErrors}),
815+
OIDCConfig:&oauth2.Config{},
807816
AccessURL:&url.URL{},
808817
Provisioners: []database.ProvisionerType{database.ProvisionerTypeEcho},
809818
Database:db,

‎provisioner/terraform/provision.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ func provisionEnv(config *proto.Provision_Config, params []*proto.ParameterValue
213213
"CODER_WORKSPACE_NAME="+config.Metadata.WorkspaceName,
214214
"CODER_WORKSPACE_OWNER="+config.Metadata.WorkspaceOwner,
215215
"CODER_WORKSPACE_OWNER_EMAIL="+config.Metadata.WorkspaceOwnerEmail,
216+
"CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN="+config.Metadata.WorkspaceOwnerOidcAccessToken,
216217
"CODER_WORKSPACE_ID="+config.Metadata.WorkspaceId,
217218
"CODER_WORKSPACE_OWNER_ID="+config.Metadata.WorkspaceOwnerId,
218219
)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp