@@ -25,6 +25,7 @@ import (
25
25
"github.com/coder/coder/v2/coderd/database/dbrollup"
26
26
"github.com/coder/coder/v2/coderd/database/dbtestutil"
27
27
"github.com/coder/coder/v2/coderd/database/dbtime"
28
+ "github.com/coder/coder/v2/coderd/provisionerdserver"
28
29
"github.com/coder/coder/v2/codersdk"
29
30
"github.com/coder/coder/v2/provisionerd/proto"
30
31
"github.com/coder/coder/v2/provisionersdk"
@@ -40,6 +41,9 @@ func TestMain(m *testing.M) {
40
41
//
41
42
//nolint:paralleltest // It uses LockIDDBPurge.
42
43
func TestPurge (t * testing.T ) {
44
+ if ! dbtestutil .WillUsePostgres () {
45
+ t .Skip ("requires postgres" )
46
+ }
43
47
ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitShort )
44
48
defer cancel ()
45
49
@@ -490,3 +494,71 @@ func containsProvisionerDaemon(daemons []database.ProvisionerDaemon, name string
490
494
return d .Name == name
491
495
})
492
496
}
497
+
498
+ func TestExpireOldAPIKeys (t * testing.T ) {
499
+ t .Parallel ()
500
+ if ! dbtestutil .WillUsePostgres () {
501
+ t .Skip ("only implemented in postgres" )
502
+ }
503
+
504
+ // Given: a number of workspaces and API keys owned by a regular user and the prebuilds system user.
505
+ var (
506
+ ctx = testutil .Context (t , testutil .WaitShort )
507
+ now = dbtime .Now ()
508
+ db , _ = dbtestutil .NewDB (t , dbtestutil .WithDumpOnFailure ())
509
+ org = dbgen .Organization (t , db , database.Organization {})
510
+ user = dbgen .User (t , db , database.User {})
511
+ tpl = dbgen .Template (t , db , database.Template {OrganizationID : org .ID , CreatedBy : user .ID })
512
+ userWs = dbgen .Workspace (t , db , database.WorkspaceTable {
513
+ OwnerID : user .ID ,
514
+ TemplateID : tpl .ID ,
515
+ })
516
+ prebuildsWs = dbgen .Workspace (t , db , database.WorkspaceTable {
517
+ OwnerID : database .PrebuildsSystemUserID ,
518
+ TemplateID : tpl .ID ,
519
+ })
520
+ createAPIKey = func (userID uuid.UUID , name string ) database.APIKey {
521
+ k , _ := dbgen .APIKey (t , db , database.APIKey {UserID : userID , TokenName : name , ExpiresAt : now .Add (time .Hour )}, func (iap * database.InsertAPIKeyParams ) {
522
+ iap .TokenName = name
523
+ })
524
+ return k
525
+ }
526
+ assertKeyActive = func (kid string ) {
527
+ k , err := db .GetAPIKeyByID (ctx , kid )
528
+ require .NoError (t , err )
529
+ assert .True (t , k .ExpiresAt .After (now ))
530
+ }
531
+ assertKeyExpired = func (kid string ) {
532
+ k , err := db .GetAPIKeyByID (ctx , kid )
533
+ require .NoError (t , err )
534
+ assert .True (t , k .ExpiresAt .Equal (now ))
535
+ }
536
+ unnamedUserAPIKey = createAPIKey (user .ID , "" )
537
+ unnamedPrebuildsAPIKey = createAPIKey (database .PrebuildsSystemUserID , "" )
538
+ namedUserAPIKey = createAPIKey (user .ID , "my-token" )
539
+ namedPrebuildsAPIKey = createAPIKey (database .PrebuildsSystemUserID , "also-my-token" )
540
+ userWorkspaceAPIKey1 = createAPIKey (user .ID , provisionerdserver .WorkspaceSessionTokenName (user .ID , userWs .ID ))
541
+ userWorkspaceAPIKey2 = createAPIKey (user .ID , provisionerdserver .WorkspaceSessionTokenName (user .ID , prebuildsWs .ID ))
542
+ prebuildsWorkspaceAPIKey1 = createAPIKey (database .PrebuildsSystemUserID , provisionerdserver .WorkspaceSessionTokenName (database .PrebuildsSystemUserID , prebuildsWs .ID ))
543
+ prebuildsWorkspaceAPIKey2 = createAPIKey (database .PrebuildsSystemUserID , provisionerdserver .WorkspaceSessionTokenName (database .PrebuildsSystemUserID , userWs .ID ))
544
+ )
545
+
546
+ // When: we call ExpirePrebuildsAPIKeys
547
+ err := db .ExpirePrebuildsAPIKeys (ctx , now )
548
+ // Then: no errors is reported.
549
+ require .NoError (t , err )
550
+
551
+ // We do not touch user API keys.
552
+ assertKeyActive (unnamedUserAPIKey .ID )
553
+ assertKeyActive (namedUserAPIKey .ID )
554
+ assertKeyActive (userWorkspaceAPIKey1 .ID )
555
+ assertKeyActive (userWorkspaceAPIKey2 .ID )
556
+ // Unnamed prebuilds API keys get expired.
557
+ assertKeyExpired (unnamedPrebuildsAPIKey .ID )
558
+ // API keys for workspaces still owned by prebuilds user remain active until claimed.
559
+ assertKeyActive (prebuildsWorkspaceAPIKey1 .ID )
560
+ // API keys for workspaces no longer owned by prebuilds user get expired.
561
+ assertKeyExpired (prebuildsWorkspaceAPIKey2 .ID )
562
+ // Out of an abundance of caution, we do not expire explicitly named prebuilds API keys.
563
+ assertKeyActive (namedPrebuildsAPIKey .ID )
564
+ }
0 commit comments