@@ -74,6 +74,12 @@ func (api *API) provisionerDaemons(rw http.ResponseWriter, r *http.Request) {
74
74
httpapi .Write (ctx , rw , http .StatusOK , db2sdk .List (daemons , db2sdk .ProvisionerDaemon ))
75
75
}
76
76
77
+ type provisiionerDaemonAuthResponse struct {
78
+ keyID uuid.UUID
79
+ orgID uuid.UUID
80
+ tags map [string ]string
81
+ }
82
+
77
83
type provisionerDaemonAuth struct {
78
84
psk string
79
85
db database.Store
@@ -82,68 +88,85 @@ type provisionerDaemonAuth struct {
82
88
83
89
// authorize returns mutated tags if the given HTTP request is authorized to access the provisioner daemon
84
90
// protobuf API, and returns nil, err otherwise.
85
- func (p * provisionerDaemonAuth ) authorize (r * http.Request , org database.Organization , tags map [string ]string ) (uuid. UUID , uuid. UUID , map [ string ] string , error ) {
91
+ func (p * provisionerDaemonAuth ) authorize (r * http.Request , org database.Organization , tags map [string ]string ) (provisiionerDaemonAuthResponse , error ) {
86
92
ctx := r .Context ()
87
93
apiKey , apiKeyOK := httpmw .APIKeyOptional (r )
88
94
pk , pkOK := httpmw .ProvisionerKeyAuthOptional (r )
89
95
provAuth := httpmw .ProvisionerDaemonAuthenticated (r )
90
96
if ! provAuth && ! apiKeyOK {
91
- return uuid . Nil , uuid . Nil , nil , xerrors .New ("no API key or provisioner key provided" )
97
+ return provisiionerDaemonAuthResponse {} , xerrors .New ("no API key or provisioner key provided" )
92
98
}
93
99
if apiKeyOK && pkOK {
94
- return uuid . Nil , uuid . Nil , nil , xerrors .New ("Both API key and provisioner key authentication provided. Only one is allowed." )
100
+ return provisiionerDaemonAuthResponse {} , xerrors .New ("Both API key and provisioner key authentication provided. Only one is allowed." )
95
101
}
96
102
97
103
// Provisioner Key Auth
98
104
if pkOK {
99
105
if tags != nil && ! maps .Equal (tags , map [string ]string {}) {
100
- return uuid . Nil , uuid . Nil , nil , xerrors .New ("tags are not allowed when using a provisioner key" )
106
+ return provisiionerDaemonAuthResponse {} , xerrors .New ("tags are not allowed when using a provisioner key" )
101
107
}
102
108
103
109
// If using provisioner key / PSK auth, the daemon is, by definition, scoped to the organization.
104
110
// Use the provisioner key tags here.
105
111
tags = provisionersdk .MutateTags (uuid .Nil , pk .Tags )
106
- return pk .ID , pk .OrganizationID , tags , nil
112
+ return provisiionerDaemonAuthResponse {
113
+ keyID : pk .ID ,
114
+ orgID : pk .OrganizationID ,
115
+ tags : tags ,
116
+ }, nil
107
117
}
108
118
109
119
// PSK Auth
110
120
if provAuth {
111
121
if ! org .IsDefault {
112
- return uuid . Nil , uuid . Nil , nil , xerrors .Errorf ("PSK auth is only allowed for the default organization '%s'" , org .Name )
122
+ return provisiionerDaemonAuthResponse {} , xerrors .Errorf ("PSK auth is only allowed for the default organization '%s'" , org .Name )
113
123
}
114
124
115
125
pskKey , err := uuid .Parse (codersdk .ProvisionerKeyIDPSK )
116
126
if err != nil {
117
- return uuid . Nil , uuid . Nil , nil , xerrors .Errorf ("parse psk provisioner key id: %w" , err )
127
+ return provisiionerDaemonAuthResponse {} , xerrors .Errorf ("parse psk provisioner key id: %w" , err )
118
128
}
119
129
120
130
tags = provisionersdk .MutateTags (uuid .Nil , tags )
121
- return pskKey , org .ID , tags , nil
131
+
132
+ return provisiionerDaemonAuthResponse {
133
+ keyID : pskKey ,
134
+ orgID : org .ID ,
135
+ tags : tags ,
136
+ }, nil
122
137
}
123
138
124
139
// User Auth
125
140
if ! apiKeyOK {
126
- return uuid . Nil , uuid . Nil , nil , xerrors .New ("no API key provided" )
141
+ return provisiionerDaemonAuthResponse {} , xerrors .New ("no API key provided" )
127
142
}
128
143
129
144
userKey , err := uuid .Parse (codersdk .ProvisionerKeyIDUserAuth )
130
145
if err != nil {
131
- return uuid . Nil , uuid . Nil , nil , xerrors .Errorf ("parse user provisioner key id: %w" , err )
146
+ return provisiionerDaemonAuthResponse {} , xerrors .Errorf ("parse user provisioner key id: %w" , err )
132
147
}
133
148
134
149
tags = provisionersdk .MutateTags (apiKey .UserID , tags )
135
150
if tags [provisionersdk .TagScope ] == provisionersdk .ScopeUser {
136
151
// Any authenticated user can create provisioner daemons scoped
137
152
// for jobs that they own,
138
- return userKey , org .ID , tags , nil
153
+ return provisiionerDaemonAuthResponse {
154
+ keyID : userKey ,
155
+ orgID : org .ID ,
156
+ tags : tags ,
157
+ }, nil
139
158
}
140
159
ua := httpmw .UserAuthorization (r )
141
160
err = p .authorizer .Authorize (ctx , ua , policy .ActionCreate , rbac .ResourceProvisionerDaemon .InOrg (org .ID ))
142
161
if err != nil {
143
- return uuid . Nil , uuid . Nil , nil , xerrors .New ("user unauthorized" )
162
+ return provisiionerDaemonAuthResponse {} , xerrors .New ("user unauthorized" )
144
163
}
145
164
146
- return userKey , org .ID , tags , nil
165
+ return provisiionerDaemonAuthResponse {
166
+ keyID : userKey ,
167
+ orgID : org .ID ,
168
+ tags : tags ,
169
+ }, nil
147
170
}
148
171
149
172
// Serves the provisioner daemon protobuf API over a WebSocket.
@@ -205,7 +228,7 @@ func (api *API) provisionerDaemonServe(rw http.ResponseWriter, r *http.Request)
205
228
api .Logger .Warn (ctx , "unnamed provisioner daemon" )
206
229
}
207
230
208
- keyID , orgID , tags , err := api .provisionerDaemonAuth .authorize (r , httpmw .OrganizationParam (r ), tags )
231
+ authRes , err := api .provisionerDaemonAuth .authorize (r , httpmw .OrganizationParam (r ), tags )
209
232
if err != nil {
210
233
api .Logger .Warn (ctx , "unauthorized provisioner daemon serve request" , slog .F ("tags" , tags ), slog .Error (err ))
211
234
httpapi .Write (ctx , rw , http .StatusForbidden ,
@@ -216,6 +239,8 @@ func (api *API) provisionerDaemonServe(rw http.ResponseWriter, r *http.Request)
216
239
)
217
240
return
218
241
}
242
+ tags = authRes .tags
243
+
219
244
api .Logger .Debug (ctx , "provisioner authorized" , slog .F ("tags" , tags ))
220
245
if err := provisionerdserver .Tags (tags ).Valid (); err != nil {
221
246
httpapi .Write (ctx , rw , http .StatusBadRequest , codersdk.Response {
@@ -277,8 +302,8 @@ func (api *API) provisionerDaemonServe(rw http.ResponseWriter, r *http.Request)
277
302
LastSeenAt : sql.NullTime {Time : now , Valid : true },
278
303
Version : versionHdrVal ,
279
304
APIVersion : apiVersion ,
280
- OrganizationID : orgID ,
281
- KeyID : keyID ,
305
+ OrganizationID : authRes . orgID ,
306
+ KeyID : authRes . keyID ,
282
307
})
283
308
if err != nil {
284
309
if ! xerrors .Is (err , context .Canceled ) {
0 commit comments