@@ -27,19 +27,18 @@ import (
2727
2828 "github.com/coreos/go-oidc/v3/oidc"
2929 "github.com/gin-gonic/gin"
30- "github.com/jmoiron/sqlx"
3130 "github.com/ulule/limiter/v3"
3231 mgin "github.com/ulule/limiter/v3/drivers/middleware/gin"
3332 "github.com/ulule/limiter/v3/drivers/store/memory"
3433 "golang.org/x/oauth2"
3534
35+ "github.com/smartcontractkit/chainlink-common/pkg/sqlutil"
3636 "github.com/smartcontractkit/chainlink-common/pkg/utils/mathutil"
3737 "github.com/smartcontractkit/chainlink/v2/core/auth"
3838 "github.com/smartcontractkit/chainlink/v2/core/bridges"
3939 "github.com/smartcontractkit/chainlink/v2/core/config"
4040 "github.com/smartcontractkit/chainlink/v2/core/logger"
4141 "github.com/smartcontractkit/chainlink/v2/core/logger/audit"
42- "github.com/smartcontractkit/chainlink/v2/core/services/pg"
4342 "github.com/smartcontractkit/chainlink/v2/core/sessions"
4443 "github.com/smartcontractkit/chainlink/v2/core/utils"
4544)
@@ -52,7 +51,7 @@ const (
5251var ErrUserNoOIDCGroups = errors .New ("user claims response from identity server recieved, but no matching role group names in claim" )
5352
5453type oidcAuthenticator struct {
55- q pg. Q
54+ ds sqlutil. DataSource
5655 config config.OIDC
5756 provider * oidc.Provider
5857 oidcConfig * oidc.Config
@@ -65,14 +64,11 @@ type oidcAuthenticator struct {
6564var _ sessions.AuthenticationProvider = (* oidcAuthenticator )(nil )
6665
6766func NewOIDCAuthenticator (
68- db * sqlx.DB ,
69- pgCfg pg.QConfig ,
67+ ds sqlutil.DataSource ,
7068 oidcCfg config.OIDC ,
7169 lggr logger.Logger ,
7270 auditLogger audit.AuditLogger ,
7371) (* oidcAuthenticator , error ) {
74- namedLogger := lggr .Named ("OIDCAuthenticationProvider" )
75-
7672 // Ensure all RBAC role mappings to OIDC Groups are defined, and required fields populated, or error on startup
7773 if oidcCfg .AdminUserGroupClaim () == "" || oidcCfg .EditUserGroupClaim () == "" ||
7874 oidcCfg .RunUserGroupClaim () == "" || oidcCfg .ReadUserGroupClaim () == "" {
@@ -116,7 +112,7 @@ func NewOIDCAuthenticator(
116112
117113 // Create Authenticator struct, with internal HTTP handlers
118114 ldapAuth := oidcAuthenticator {
119- q : pg . NewQ ( db , namedLogger , pgCfg ) ,
115+ ds : ds ,
120116 config : oidcCfg ,
121117 provider : provider ,
122118 oidcConfig : oidcConfig ,
@@ -211,7 +207,8 @@ func (oi *oidcAuthenticator) handleOIDCCallback(w http.ResponseWriter, r *http.R
211207 // Save new user authenticated session and role to oidc_sessions table
212208 // Sessions are set to expire after the duration + creation date elapsed
213209 session := sessions .NewSession ()
214- _ , err = oi .q .Exec (
210+ _ , err = oi .ds .ExecContext (
211+ ctx ,
215212 "INSERT INTO oidc_sessions (id, user_email, user_role, created_at) VALUES ($1, $2, $3, $4, now())" ,
216213 session .ID ,
217214 strings .ToLower (claims .Email ),
@@ -236,14 +233,14 @@ func (oi *oidcAuthenticator) handleOIDCCallback(w http.ResponseWriter, r *http.R
236233}
237234
238235// FindUser in the context of the OIDC driver only supports local admin users
239- func (oi * oidcAuthenticator ) FindUser (email string ) (sessions.User , error ) {
236+ func (oi * oidcAuthenticator ) FindUser (ctx context. Context , email string ) (sessions.User , error ) {
240237 email = strings .ToLower (email )
241238 foundUser := sessions.User {}
242239
243240 var foundLocalAdminUser sessions.User
244- checkErr := oi . q . Transaction ( func (tx pg. Queryer ) error {
241+ checkErr := sqlutil . TransactDataSource ( ctx , oi . ds , nil , func (tx sqlutil. DataSource ) error {
245242 sql := "SELECT * FROM users WHERE lower(email) = lower($1)"
246- return tx .Get ( & foundLocalAdminUser , sql , email )
243+ return tx .GetContext ( ctx , & foundLocalAdminUser , sql , email )
247244 })
248245 if checkErr == nil {
249246 return foundLocalAdminUser , nil
@@ -259,13 +256,13 @@ func (oi *oidcAuthenticator) FindUser(email string) (sessions.User, error) {
259256}
260257
261258// FindUserByAPIToken retrieves a possible stored user and role from the oidc_user_api_tokens table store
262- func (oi * oidcAuthenticator ) FindUserByAPIToken (apiToken string ) (sessions.User , error ) {
259+ func (oi * oidcAuthenticator ) FindUserByAPIToken (ctx context. Context , apiToken string ) (sessions.User , error ) {
263260 if ! oi .config .UserApiTokenEnabled () {
264261 return sessions.User {}, errors .New ("API token is not enabled " )
265262 }
266263
267264 var foundUser sessions.User
268- err := oi . q . Transaction ( func (tx pg. Queryer ) error {
265+ err := sqlutil . TransactDataSource ( ctx , oi . ds , nil , func (tx sqlutil. DataSource ) error {
269266 // Query the oidc user API token table for given token, user role and email are cached so
270267 // no further upstream OIDC query is performed, sessions and tokens are synced against the upstream server
271268 // via the UpstreamSyncInterval config and reaper.go sync implementation
@@ -274,7 +271,7 @@ func (oi *oidcAuthenticator) FindUserByAPIToken(apiToken string) (sessions.User,
274271 UserRole sessions.UserRole
275272 Valid bool
276273 }
277- if err := tx .Get ( & foundUserToken ,
274+ if err := tx .GetContext ( ctx , & foundUserToken ,
278275 "SELECT user_email, user_role, created_at + $2 >= now() as valid FROM oidc_user_api_tokens WHERE token_key = $1" ,
279276 apiToken , oi .config .UserAPITokenDuration ().Duration (),
280277 ); err != nil {
@@ -292,7 +289,7 @@ func (oi *oidcAuthenticator) FindUserByAPIToken(apiToken string) (sessions.User,
292289 if err != nil {
293290 if errors .Is (err , sessions .ErrUserSessionExpired ) {
294291 // API Token expired, purge
295- if _ , execErr := oi .q . Exec ( "DELETE FROM oidc_user_api_tokens WHERE token_key = $1" , apiToken ); err != nil {
292+ if _ , execErr := oi .ds . ExecContext ( ctx , "DELETE FROM oidc_user_api_tokens WHERE token_key = $1" , apiToken ); err != nil {
296293 oi .lggr .Errorf ("error purging stale oidc API token session: %v" , execErr )
297294 }
298295 }
@@ -302,32 +299,33 @@ func (oi *oidcAuthenticator) FindUserByAPIToken(apiToken string) (sessions.User,
302299}
303300
304301// ListUsers in the context of the OIDC driver only supports listing the local (admin) users, we don't have an identity server to query against
305- func (oi * oidcAuthenticator ) ListUsers () ([]sessions.User , error ) {
302+ func (oi * oidcAuthenticator ) ListUsers (ctx context. Context ) ([]sessions.User , error ) {
306303 returnUsers := []sessions.User {}
307- if err := oi . q . Transaction ( func (tx pg. Queryer ) error {
304+ if err := sqlutil . TransactDataSource ( ctx , oi . ds , nil , func (tx sqlutil. DataSource ) error {
308305 sql := "SELECT * FROM users ORDER BY email ASC;"
309- return tx .Select (& returnUsers , sql )
310- }); err != nil {
306+ return tx .SelectContext (ctx , & returnUsers , sql )
307+ })
308+ err != nil {
311309 oi .lggr .Errorf ("error listing local users: " , err )
312310 }
313311 return returnUsers , nil
314312}
315313
316314// AuthorizedUserWithSession will return the API user associated with the Session ID if it
317315// exists and hasn't expired, and update session's LastUsed field
318- func (oi * oidcAuthenticator ) AuthorizedUserWithSession (sessionID string ) (sessions.User , error ) {
316+ func (oi * oidcAuthenticator ) AuthorizedUserWithSession (ctx context. Context , sessionID string ) (sessions.User , error ) {
319317 if len (sessionID ) == 0 {
320318 return sessions.User {}, errors .New ("session ID cannot be empty" )
321319 }
322320 var foundUser sessions.User
323- err := oi . q . Transaction ( func (tx pg. Queryer ) error {
321+ err := sqlutil . TransactDataSource ( ctx , oi . ds , nil , func (tx sqlutil. DataSource ) error {
324322 // Query the oidc_sessions table for given session ID, user role and email are saved after the SAML groups claim is provided and validated
325323 var foundSession struct {
326324 UserEmail string
327325 UserRole sessions.UserRole
328326 Valid bool
329327 }
330- if err := tx .Get ( & foundSession ,
328+ if err := tx .GetContext ( ctx , & foundSession ,
331329 "SELECT user_email, user_role, created_at + $2 >= now() as valid FROM oidc_sessions WHERE id = $1" ,
332330 sessionID , oi .config .SessionTimeout ().Duration (),
333331 ); err != nil {
@@ -345,7 +343,7 @@ func (oi *oidcAuthenticator) AuthorizedUserWithSession(sessionID string) (sessio
345343 })
346344 if err != nil {
347345 if errors .Is (err , sessions .ErrUserSessionExpired ) {
348- if _ , execErr := oi .q . Exec ( "DELETE FROM oidc_sessions WHERE id = $1" , sessionID ); err != nil {
346+ if _ , execErr := oi .ds . ExecContext ( ctx , "DELETE FROM oidc_sessions WHERE id = $1" , sessionID ); err != nil {
349347 oi .lggr .Errorf ("error purging stale OIDC session: %v" , execErr )
350348 }
351349 }
@@ -355,26 +353,26 @@ func (oi *oidcAuthenticator) AuthorizedUserWithSession(sessionID string) (sessio
355353}
356354
357355// DeleteUser is not supported for read only OIDC
358- func (oi * oidcAuthenticator ) DeleteUser (email string ) error {
356+ func (oi * oidcAuthenticator ) DeleteUser (ctx context. Context , email string ) error {
359357 return sessions .ErrNotSupported
360358}
361359
362360// DeleteUserSession removes an oidcSession table entry by ID
363- func (oi * oidcAuthenticator ) DeleteUserSession (sessionID string ) error {
364- _ , err := oi .q . Exec ( "DELETE FROM oidc_sessions WHERE id = $1" , sessionID )
361+ func (oi * oidcAuthenticator ) DeleteUserSession (ctx context. Context , sessionID string ) error {
362+ _ , err := oi .ds . ExecContext ( ctx , "DELETE FROM oidc_sessions WHERE id = $1" , sessionID )
365363 return err
366364}
367365
368366// GetUserWebAuthn returns an empty stub, MFA is delegated to SAML provider
369- func (oi * oidcAuthenticator ) GetUserWebAuthn (email string ) ([]sessions.WebAuthn , error ) {
367+ func (oi * oidcAuthenticator ) GetUserWebAuthn (ctx context. Context , email string ) ([]sessions.WebAuthn , error ) {
370368 return []sessions.WebAuthn {}, nil
371369}
372370
373371// CreateSession in the context of the OIDC driver handles only the local auth admin user, exposed by the default endpoint defined in the router. To initiate the SAML/OIDC
374372// flow, a separate /oidc-login route is defined which handles the redirect to the
375373// configured provider
376- func (oi * oidcAuthenticator ) CreateSession (sr sessions.SessionRequest ) (string , error ) {
377- foundUser , err := oi .localLoginFallback (sr )
374+ func (oi * oidcAuthenticator ) CreateSession (ctx context. Context , sr sessions.SessionRequest ) (string , error ) {
375+ foundUser , err := oi .localLoginFallback (ctx , sr )
378376 if err != nil {
379377 return "" , err
380378 }
@@ -384,7 +382,7 @@ func (oi *oidcAuthenticator) CreateSession(sr sessions.SessionRequest) (string,
384382 // Save local admin session, user, and role to sessions table
385383 // Sessions are set to expire after the duration + creation date elapsed
386384 session := sessions .NewSession ()
387- _ , err = oi .q . Exec (
385+ _ , err = oi .ds . ExecContext ( ctx ,
388386 "INSERT INTO oidc_sessions (id, user_email, user_role, created_at) VALUES ($1, $2, $3, $4, now())" ,
389387 session .ID ,
390388 strings .ToLower (sr .Email ),
@@ -401,30 +399,31 @@ func (oi *oidcAuthenticator) CreateSession(sr sessions.SessionRequest) (string,
401399}
402400
403401// ClearNonCurrentSessions removes all oicd_sessions but the id passed in.
404- func (oi * oidcAuthenticator ) ClearNonCurrentSessions (sessionID string ) error {
405- _ , err := oi .q . Exec ( "DELETE FROM oicd_sessions where id != $1" , sessionID )
402+ func (oi * oidcAuthenticator ) ClearNonCurrentSessions (ctx context. Context , sessionID string ) error {
403+ _ , err := oi .ds . ExecContext ( ctx , "DELETE FROM oicd_sessions where id != $1" , sessionID )
406404 return err
407405}
408406
409407// CreateUser is not supported for read only OIDC
410- func (oi * oidcAuthenticator ) CreateUser (user * sessions.User ) error {
408+ func (oi * oidcAuthenticator ) CreateUser (ctx context. Context , user * sessions.User ) error {
411409 return sessions .ErrNotSupported
412410}
413411
414412// UpdateRole is not supported for read only OIDC
415- func (oi * oidcAuthenticator ) UpdateRole (email , newRole string ) (sessions.User , error ) {
413+ func (oi * oidcAuthenticator ) UpdateRole (ctx context. Context , email string , newRole string ) (sessions.User , error ) {
416414 return sessions.User {}, sessions .ErrNotSupported
417415}
418416
419417// SetPassword for remote users is not supported via the read only OIDC implementation, however change password
420418// in the context of updating a local admin user's password is required
421- func (oi * oidcAuthenticator ) SetPassword (user * sessions.User , newPassword string ) error {
419+ func (oi * oidcAuthenticator ) SetPassword (ctx context. Context , user * sessions.User , newPassword string ) error {
422420 // Ensure specified user is part of the local admins user table
423421 var localAdminUser sessions.User
424- if err := oi . q . Transaction ( func (tx pg. Queryer ) error {
422+ if err := sqlutil . TransactDataSource ( ctx , oi . ds , nil , func (tx sqlutil. DataSource ) error {
425423 sql := "SELECT * FROM users WHERE lower(email) = lower($1)"
426- return tx .Get (& localAdminUser , sql , user .Email )
427- }); err != nil {
424+ return tx .GetContext (ctx , & localAdminUser , sql , user .Email )
425+ });
426+ err != nil {
428427 oi .lggr .Infof ("Can not change password, local user with email not found in users table: %s, err: %v" , user .Email , err )
429428 return sessions .ErrNotSupported
430429 }
@@ -434,21 +433,22 @@ func (oi *oidcAuthenticator) SetPassword(user *sessions.User, newPassword string
434433 if err != nil {
435434 return err
436435 }
437- if err := oi . q . Transaction ( func (tx pg. Queryer ) error {
436+ if err := sqlutil . TransactDataSource ( ctx , oi . ds , nil , func (tx sqlutil. DataSource ) error {
438437 sql := "UPDATE users SET hashed_password = $1, updated_at = now() WHERE email = $2 RETURNING *"
439- return tx .Get (user , sql , hashedPassword , user .Email )
440- }); err != nil {
438+ return tx .GetContext (ctx , user , sql , hashedPassword , user .Email )
439+ });
440+ err != nil {
441441 oi .lggr .Errorf ("unable to set password for user: %s, err: %v" , user .Email , err )
442442 return errors .New ("unable to save password" )
443443 }
444444 return nil
445445}
446446
447447// TestPassword only supports the potential local admin user, as there is no queryable identity server for the OIDC implementation
448- func (oi * oidcAuthenticator ) TestPassword (email string , password string ) error {
448+ func (oi * oidcAuthenticator ) TestPassword (ctx context. Context , email string , password string ) error {
449449 // Fall back to test local users table in case of supported local CLI users as well
450450 var hashedPassword string
451- if err := oi .q . Get ( & hashedPassword , "SELECT hashed_password FROM users WHERE lower(email) = lower($1)" , email ); err != nil {
451+ if err := oi .ds . GetContext ( ctx , & hashedPassword , "SELECT hashed_password FROM users WHERE lower(email) = lower($1)" , email ); err != nil {
452452 return errors .New ("invalid credentials" )
453453 }
454454 if ! utils .CheckPasswordHash (password , hashedPassword ) {
@@ -458,17 +458,17 @@ func (oi *oidcAuthenticator) TestPassword(email string, password string) error {
458458}
459459
460460// CreateAndSetAuthToken generates a new credential token with the user role
461- func (oi * oidcAuthenticator ) CreateAndSetAuthToken (user * sessions.User ) (* auth.Token , error ) {
461+ func (oi * oidcAuthenticator ) CreateAndSetAuthToken (ctx context. Context , user * sessions.User ) (* auth.Token , error ) {
462462 newToken := auth .NewToken ()
463- err := oi .SetAuthToken (user , newToken )
463+ err := oi .SetAuthToken (ctx , user , newToken )
464464 if err != nil {
465465 return nil , err
466466 }
467467 return newToken , nil
468468}
469469
470470// SetAuthToken updates the user to use the given Authentication Token.
471- func (oi * oidcAuthenticator ) SetAuthToken (user * sessions.User , token * auth.Token ) error {
471+ func (oi * oidcAuthenticator ) SetAuthToken (ctx context. Context , user * sessions.User , token * auth.Token ) error {
472472 if ! oi .config .UserApiTokenEnabled () {
473473 return errors .New ("API token is not enabled " )
474474 }
@@ -479,13 +479,13 @@ func (oi *oidcAuthenticator) SetAuthToken(user *sessions.User, token *auth.Token
479479 return fmt .Errorf ("OIDCAuth SetAuthToken hashed secret error: %w" , err )
480480 }
481481
482- err = oi . q . Transaction ( func (tx pg. Queryer ) error {
482+ err = sqlutil . TransactDataSource ( ctx , oi . ds , nil , func (tx sqlutil. DataSource ) error {
483483 // Remove any existing API tokens
484- if _ , err = oi .q . Exec ( "DELETE FROM oidc_user_api_tokens WHERE user_email = $1" , user .Email ); err != nil {
484+ if _ , err = oi .ds . ExecContext ( ctx , "DELETE FROM oidc_user_api_tokens WHERE user_email = $1" , user .Email ); err != nil {
485485 return fmt .Errorf ("error executing DELETE FROM oidc_user_api_tokens: %w" , err )
486486 }
487487 // Create new API token for user
488- _ , err = oi .q . Exec (
488+ _ , err = oi .ds . ExecContext ( ctx ,
489489 "INSERT INTO oidc_user_api_tokens (user_email, user_role, token_key, token_salt, token_hashed_secret, created_at) VALUES ($1, $2, $3, $4, $5, $6, now())" ,
490490 user .Email ,
491491 user .Role ,
@@ -507,39 +507,39 @@ func (oi *oidcAuthenticator) SetAuthToken(user *sessions.User, token *auth.Token
507507}
508508
509509// DeleteAuthToken clears and disables the users Authentication Token.
510- func (oi * oidcAuthenticator ) DeleteAuthToken (user * sessions.User ) error {
511- _ , err := oi .q . Exec ( "DELETE FROM oidc_user_api_tokens WHERE email = $1" )
510+ func (oi * oidcAuthenticator ) DeleteAuthToken (ctx context. Context , user * sessions.User ) error {
511+ _ , err := oi .ds . ExecContext ( ctx , "DELETE FROM oidc_user_api_tokens WHERE email = $1" )
512512 return err
513513}
514514
515515// SaveWebAuthn is not supported for read only OIDC
516- func (oi * oidcAuthenticator ) SaveWebAuthn (token * sessions.WebAuthn ) error {
516+ func (oi * oidcAuthenticator ) SaveWebAuthn (ctx context. Context , token * sessions.WebAuthn ) error {
517517 return sessions .ErrNotSupported
518518}
519519
520520// Sessions returns all sessions limited by the parameters.
521- func (oi * oidcAuthenticator ) Sessions (offset , limit int ) ([]sessions.Session , error ) {
521+ func (oi * oidcAuthenticator ) Sessions (ctx context. Context , offset , limit int ) ([]sessions.Session , error ) {
522522 var sessions []sessions.Session
523523 sql := `SELECT * FROM oidc_sessions ORDER BY created_at, id LIMIT $1 OFFSET $2;`
524- if err := oi .q . Select ( & sessions , sql , limit , offset ); err != nil {
524+ if err := oi .ds . SelectContext ( ctx , & sessions , sql , limit , offset ); err != nil {
525525 return sessions , nil
526526 }
527527 return sessions , nil
528528}
529529
530530// FindExternalInitiator supports the 'Run' role external intiator header auth functionality
531- func (oi * oidcAuthenticator ) FindExternalInitiator (eia * auth.Token ) (* bridges.ExternalInitiator , error ) {
531+ func (oi * oidcAuthenticator ) FindExternalInitiator (ctx context. Context , eia * auth.Token ) (* bridges.ExternalInitiator , error ) {
532532 exi := & bridges.ExternalInitiator {}
533- err := oi .q . Get ( exi , `SELECT * FROM external_initiators WHERE access_key = $1` , eia .AccessKey )
533+ err := oi .ds . GetContext ( ctx , exi , `SELECT * FROM external_initiators WHERE access_key = $1` , eia .AccessKey )
534534 return exi , err
535535}
536536
537537// localLoginFallback tests the credentials provided against the 'local' authentication method
538538// This covers the case of local CLI API calls requiring local login separate from the OIDC server
539- func (oi * oidcAuthenticator ) localLoginFallback (sr sessions.SessionRequest ) (sessions.User , error ) {
539+ func (oi * oidcAuthenticator ) localLoginFallback (ctx context. Context , sr sessions.SessionRequest ) (sessions.User , error ) {
540540 var user sessions.User
541541 sql := "SELECT * FROM users WHERE lower(email) = lower($1)"
542- err := oi .q . Get ( & user , sql , sr .Email )
542+ err := oi .ds . GetContext ( ctx , & user , sql , sr .Email )
543543 if err != nil {
544544 return user , err
545545 }
0 commit comments