@@ -15,6 +15,7 @@ import (
1515"github.com/coder/coder/v2/coderd/audit"
1616"github.com/coder/coder/v2/coderd/coderdtest"
1717"github.com/coder/coder/v2/coderd/database"
18+ "github.com/coder/coder/v2/coderd/database/dbgen"
1819"github.com/coder/coder/v2/coderd/rbac"
1920"github.com/coder/coder/v2/codersdk"
2021"github.com/coder/coder/v2/provisioner/echo"
@@ -531,3 +532,112 @@ func completeWithAgentAndApp() *echo.Responses {
531532},
532533}
533534}
535+
536+ // TestDeprecatedConnEvents tests the deprecated connection and disconnection
537+ // events in the audit logs. These events are no longer created, but need to be
538+ // returned by the API.
539+ func TestDeprecatedConnEvents (t * testing.T ) {
540+ t .Parallel ()
541+ var (
542+ ctx = context .Background ()
543+ client ,_ ,api = coderdtest .NewWithAPI (t ,& coderdtest.Options {IncludeProvisionerDaemon :true })
544+ user = coderdtest .CreateFirstUser (t ,client )
545+ version = coderdtest .CreateTemplateVersion (t ,client ,user .OrganizationID ,completeWithAgentAndApp ())
546+ template = coderdtest .CreateTemplate (t ,client ,user .OrganizationID ,version .ID )
547+ )
548+
549+ coderdtest .AwaitTemplateVersionJobCompleted (t ,client ,version .ID )
550+ workspace := coderdtest .CreateWorkspace (t ,client ,template .ID )
551+ workspace .LatestBuild = coderdtest .AwaitWorkspaceBuildJobCompleted (t ,client ,workspace .LatestBuild .ID )
552+
553+ type additionalFields struct {
554+ audit.AdditionalFields
555+ ConnectionType string `json:"connection_type"`
556+ }
557+
558+ sshFields := additionalFields {
559+ AdditionalFields : audit.AdditionalFields {
560+ WorkspaceName :workspace .Name ,
561+ BuildNumber :"999" ,
562+ BuildReason :"initiator" ,
563+ WorkspaceOwner :workspace .OwnerName ,
564+ WorkspaceID :workspace .ID ,
565+ },
566+ ConnectionType :"SSH" ,
567+ }
568+
569+ sshFieldsBytes ,err := json .Marshal (sshFields )
570+ require .NoError (t ,err )
571+
572+ appFields := audit.AdditionalFields {
573+ WorkspaceName :workspace .Name ,
574+ // Deliberately empty
575+ BuildNumber :"" ,
576+ BuildReason :"" ,
577+ WorkspaceOwner :workspace .OwnerName ,
578+ WorkspaceID :workspace .ID ,
579+ }
580+
581+ appFieldsBytes ,err := json .Marshal (appFields )
582+ require .NoError (t ,err )
583+
584+ dbgen .AuditLog (t ,api .Database , database.AuditLog {
585+ OrganizationID :user .OrganizationID ,
586+ Action :database .AuditActionConnect ,
587+ ResourceType :database .ResourceTypeWorkspaceAgent ,
588+ ResourceID :workspace .LatestBuild .Resources [0 ].Agents [0 ].ID ,
589+ ResourceTarget :workspace .LatestBuild .Resources [0 ].Agents [0 ].Name ,
590+ Time :time .Date (2022 ,8 ,15 ,14 ,30 ,45 ,100 ,time .UTC ),// 2022-8-15 14:30:45
591+ AdditionalFields :sshFieldsBytes ,
592+ })
593+
594+ dbgen .AuditLog (t ,api .Database , database.AuditLog {
595+ OrganizationID :user .OrganizationID ,
596+ Action :database .AuditActionDisconnect ,
597+ ResourceType :database .ResourceTypeWorkspaceAgent ,
598+ ResourceID :workspace .LatestBuild .Resources [0 ].Agents [0 ].ID ,
599+ ResourceTarget :workspace .LatestBuild .Resources [0 ].Agents [0 ].Name ,
600+ Time :time .Date (2022 ,8 ,15 ,14 ,35 ,0o0 ,100 ,time .UTC ),// 2022-8-15 14:35:00
601+ AdditionalFields :sshFieldsBytes ,
602+ })
603+
604+ dbgen .AuditLog (t ,api .Database , database.AuditLog {
605+ OrganizationID :user .OrganizationID ,
606+ UserID :user .UserID ,
607+ Action :database .AuditActionOpen ,
608+ ResourceType :database .ResourceTypeWorkspaceApp ,
609+ ResourceID :workspace .LatestBuild .Resources [0 ].Agents [0 ].Apps [0 ].ID ,
610+ ResourceTarget :workspace .LatestBuild .Resources [0 ].Agents [0 ].Apps [0 ].Slug ,
611+ Time :time .Date (2022 ,8 ,15 ,14 ,30 ,45 ,100 ,time .UTC ),// 2022-8-15 14:30:45
612+ AdditionalFields :appFieldsBytes ,
613+ })
614+
615+ connLog ,err := client .AuditLogs (ctx , codersdk.AuditLogsRequest {
616+ SearchQuery :"action:connect" ,
617+ })
618+ require .NoError (t ,err )
619+ require .Len (t ,connLog .AuditLogs ,1 )
620+ var sshOutFields additionalFields
621+ err = json .Unmarshal (connLog .AuditLogs [0 ].AdditionalFields ,& sshOutFields )
622+ require .NoError (t ,err )
623+ require .Equal (t ,sshFields ,sshOutFields )
624+
625+ dcLog ,err := client .AuditLogs (ctx , codersdk.AuditLogsRequest {
626+ SearchQuery :"action:disconnect" ,
627+ })
628+ require .NoError (t ,err )
629+ require .Len (t ,dcLog .AuditLogs ,1 )
630+ err = json .Unmarshal (dcLog .AuditLogs [0 ].AdditionalFields ,& sshOutFields )
631+ require .NoError (t ,err )
632+ require .Equal (t ,sshFields ,sshOutFields )
633+
634+ openLog ,err := client .AuditLogs (ctx , codersdk.AuditLogsRequest {
635+ SearchQuery :"action:open" ,
636+ })
637+ require .NoError (t ,err )
638+ require .Len (t ,openLog .AuditLogs ,1 )
639+ var appOutFields audit.AdditionalFields
640+ err = json .Unmarshal (openLog .AuditLogs [0 ].AdditionalFields ,& appOutFields )
641+ require .NoError (t ,err )
642+ require .Equal (t ,appFields ,appOutFields )
643+ }