mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add workspace agent connect and app open audit types (#16493)
This commit adds new audit resource types for workspace agents and workspace apps, as well as connect/disconnect and open/close actions. The idea is that we will log new audit events for connecting to the agent via SSH/editor. Likewise, we will log openings of `coder_app`s. This change also introduces support for filtering by `request_id`. Updates #15139
This commit is contained in:
+171
-26
@@ -17,6 +17,8 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/rbac"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/coder/v2/provisioner/echo"
|
||||
"github.com/coder/coder/v2/provisionersdk/proto"
|
||||
)
|
||||
|
||||
func TestAuditLogs(t *testing.T) {
|
||||
@@ -30,7 +32,8 @@ func TestAuditLogs(t *testing.T) {
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
|
||||
err := client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
|
||||
ResourceID: user.UserID,
|
||||
ResourceID: user.UserID,
|
||||
OrganizationID: user.OrganizationID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -54,7 +57,8 @@ func TestAuditLogs(t *testing.T) {
|
||||
client2, user2 := coderdtest.CreateAnotherUser(t, client, user.OrganizationID, rbac.RoleOwner())
|
||||
|
||||
err := client2.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
|
||||
ResourceID: user2.ID,
|
||||
ResourceID: user2.ID,
|
||||
OrganizationID: user.OrganizationID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -123,6 +127,7 @@ func TestAuditLogs(t *testing.T) {
|
||||
ResourceType: codersdk.ResourceTypeWorkspaceBuild,
|
||||
ResourceID: workspace.LatestBuild.ID,
|
||||
AdditionalFields: wriBytes,
|
||||
OrganizationID: user.OrganizationID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -158,7 +163,8 @@ func TestAuditLogs(t *testing.T) {
|
||||
|
||||
// Add an extra audit log in another organization
|
||||
err = client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
|
||||
ResourceID: owner.UserID,
|
||||
ResourceID: owner.UserID,
|
||||
OrganizationID: uuid.New(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -229,53 +235,102 @@ func TestAuditLogsFilter(t *testing.T) {
|
||||
ctx = context.Background()
|
||||
client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
user = coderdtest.CreateFirstUser(t, client)
|
||||
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, completeWithAgentAndApp())
|
||||
template = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
)
|
||||
|
||||
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
|
||||
workspace := coderdtest.CreateWorkspace(t, client, template.ID)
|
||||
workspace.LatestBuild = coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
|
||||
|
||||
// Create two logs with "Create"
|
||||
err := client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
|
||||
Action: codersdk.AuditActionCreate,
|
||||
ResourceType: codersdk.ResourceTypeTemplate,
|
||||
ResourceID: template.ID,
|
||||
Time: time.Date(2022, 8, 15, 14, 30, 45, 100, time.UTC), // 2022-8-15 14:30:45
|
||||
OrganizationID: user.OrganizationID,
|
||||
Action: codersdk.AuditActionCreate,
|
||||
ResourceType: codersdk.ResourceTypeTemplate,
|
||||
ResourceID: template.ID,
|
||||
Time: time.Date(2022, 8, 15, 14, 30, 45, 100, time.UTC), // 2022-8-15 14:30:45
|
||||
})
|
||||
require.NoError(t, err)
|
||||
err = client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
|
||||
Action: codersdk.AuditActionCreate,
|
||||
ResourceType: codersdk.ResourceTypeUser,
|
||||
ResourceID: user.UserID,
|
||||
Time: time.Date(2022, 8, 16, 14, 30, 45, 100, time.UTC), // 2022-8-16 14:30:45
|
||||
OrganizationID: user.OrganizationID,
|
||||
Action: codersdk.AuditActionCreate,
|
||||
ResourceType: codersdk.ResourceTypeUser,
|
||||
ResourceID: user.UserID,
|
||||
Time: time.Date(2022, 8, 16, 14, 30, 45, 100, time.UTC), // 2022-8-16 14:30:45
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create one log with "Delete"
|
||||
err = client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
|
||||
Action: codersdk.AuditActionDelete,
|
||||
ResourceType: codersdk.ResourceTypeUser,
|
||||
ResourceID: user.UserID,
|
||||
Time: time.Date(2022, 8, 15, 14, 30, 45, 100, time.UTC), // 2022-8-15 14:30:45
|
||||
OrganizationID: user.OrganizationID,
|
||||
Action: codersdk.AuditActionDelete,
|
||||
ResourceType: codersdk.ResourceTypeUser,
|
||||
ResourceID: user.UserID,
|
||||
Time: time.Date(2022, 8, 15, 14, 30, 45, 100, time.UTC), // 2022-8-15 14:30:45
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create one log with "Start"
|
||||
err = client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
|
||||
Action: codersdk.AuditActionStart,
|
||||
ResourceType: codersdk.ResourceTypeWorkspaceBuild,
|
||||
ResourceID: workspace.LatestBuild.ID,
|
||||
Time: time.Date(2022, 8, 15, 14, 30, 45, 100, time.UTC), // 2022-8-15 14:30:45
|
||||
OrganizationID: user.OrganizationID,
|
||||
Action: codersdk.AuditActionStart,
|
||||
ResourceType: codersdk.ResourceTypeWorkspaceBuild,
|
||||
ResourceID: workspace.LatestBuild.ID,
|
||||
Time: time.Date(2022, 8, 15, 14, 30, 45, 100, time.UTC), // 2022-8-15 14:30:45
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create one log with "Stop"
|
||||
err = client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
|
||||
Action: codersdk.AuditActionStop,
|
||||
ResourceType: codersdk.ResourceTypeWorkspaceBuild,
|
||||
ResourceID: workspace.LatestBuild.ID,
|
||||
Time: time.Date(2022, 8, 15, 14, 30, 45, 100, time.UTC), // 2022-8-15 14:30:45
|
||||
OrganizationID: user.OrganizationID,
|
||||
Action: codersdk.AuditActionStop,
|
||||
ResourceType: codersdk.ResourceTypeWorkspaceBuild,
|
||||
ResourceID: workspace.LatestBuild.ID,
|
||||
Time: time.Date(2022, 8, 15, 14, 30, 45, 100, time.UTC), // 2022-8-15 14:30:45
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create one log with "Connect" and "Disconect".
|
||||
connectRequestID := uuid.New()
|
||||
err = client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
|
||||
OrganizationID: user.OrganizationID,
|
||||
Action: codersdk.AuditActionConnect,
|
||||
RequestID: connectRequestID,
|
||||
ResourceType: codersdk.ResourceTypeWorkspaceAgent,
|
||||
ResourceID: workspace.LatestBuild.Resources[0].Agents[0].ID,
|
||||
Time: time.Date(2022, 8, 15, 14, 30, 45, 100, time.UTC), // 2022-8-15 14:30:45
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
|
||||
OrganizationID: user.OrganizationID,
|
||||
Action: codersdk.AuditActionDisconnect,
|
||||
RequestID: connectRequestID,
|
||||
ResourceType: codersdk.ResourceTypeWorkspaceAgent,
|
||||
ResourceID: workspace.LatestBuild.Resources[0].Agents[0].ID,
|
||||
Time: time.Date(2022, 8, 15, 14, 35, 0o0, 100, time.UTC), // 2022-8-15 14:35:00
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create one log with "Open" and "Close".
|
||||
openRequestID := uuid.New()
|
||||
err = client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
|
||||
OrganizationID: user.OrganizationID,
|
||||
Action: codersdk.AuditActionOpen,
|
||||
RequestID: openRequestID,
|
||||
ResourceType: codersdk.ResourceTypeWorkspaceApp,
|
||||
ResourceID: workspace.LatestBuild.Resources[0].Agents[0].Apps[0].ID,
|
||||
Time: time.Date(2022, 8, 15, 14, 30, 45, 100, time.UTC), // 2022-8-15 14:30:45
|
||||
})
|
||||
require.NoError(t, err)
|
||||
err = client.CreateTestAuditLog(ctx, codersdk.CreateTestAuditLogRequest{
|
||||
OrganizationID: user.OrganizationID,
|
||||
Action: codersdk.AuditActionClose,
|
||||
RequestID: openRequestID,
|
||||
ResourceType: codersdk.ResourceTypeWorkspaceApp,
|
||||
ResourceID: workspace.LatestBuild.Resources[0].Agents[0].Apps[0].ID,
|
||||
Time: time.Date(2022, 8, 15, 14, 35, 0o0, 100, time.UTC), // 2022-8-15 14:35:00
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -309,12 +364,12 @@ func TestAuditLogsFilter(t *testing.T) {
|
||||
{
|
||||
Name: "FilterByEmail",
|
||||
SearchQuery: "email:" + coderdtest.FirstUserParams.Email,
|
||||
ExpectedResult: 5,
|
||||
ExpectedResult: 9,
|
||||
},
|
||||
{
|
||||
Name: "FilterByUsername",
|
||||
SearchQuery: "username:" + coderdtest.FirstUserParams.Username,
|
||||
ExpectedResult: 5,
|
||||
ExpectedResult: 9,
|
||||
},
|
||||
{
|
||||
Name: "FilterByResourceID",
|
||||
@@ -366,6 +421,36 @@ func TestAuditLogsFilter(t *testing.T) {
|
||||
SearchQuery: "resource_type:workspace_build action:start build_reason:initiator",
|
||||
ExpectedResult: 1,
|
||||
},
|
||||
{
|
||||
Name: "FilterOnWorkspaceAgentConnect",
|
||||
SearchQuery: "resource_type:workspace_agent action:connect",
|
||||
ExpectedResult: 1,
|
||||
},
|
||||
{
|
||||
Name: "FilterOnWorkspaceAgentDisconnect",
|
||||
SearchQuery: "resource_type:workspace_agent action:disconnect",
|
||||
ExpectedResult: 1,
|
||||
},
|
||||
{
|
||||
Name: "FilterOnWorkspaceAgentConnectionRequestID",
|
||||
SearchQuery: "resource_type:workspace_agent request_id:" + connectRequestID.String(),
|
||||
ExpectedResult: 2,
|
||||
},
|
||||
{
|
||||
Name: "FilterOnWorkspaceAppOpen",
|
||||
SearchQuery: "resource_type:workspace_app action:open",
|
||||
ExpectedResult: 1,
|
||||
},
|
||||
{
|
||||
Name: "FilterOnWorkspaceAppClose",
|
||||
SearchQuery: "resource_type:workspace_app action:close",
|
||||
ExpectedResult: 1,
|
||||
},
|
||||
{
|
||||
Name: "FilterOnWorkspaceAppOpenRequestID",
|
||||
SearchQuery: "resource_type:workspace_app request_id:" + openRequestID.String(),
|
||||
ExpectedResult: 2,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
@@ -387,3 +472,63 @@ func TestAuditLogsFilter(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func completeWithAgentAndApp() *echo.Responses {
|
||||
return &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
ProvisionPlan: []*proto.Response{
|
||||
{
|
||||
Type: &proto.Response_Plan{
|
||||
Plan: &proto.PlanComplete{
|
||||
Resources: []*proto.Resource{
|
||||
{
|
||||
Type: "compute",
|
||||
Name: "main",
|
||||
Agents: []*proto.Agent{
|
||||
{
|
||||
Name: "smith",
|
||||
OperatingSystem: "linux",
|
||||
Architecture: "i386",
|
||||
Apps: []*proto.App{
|
||||
{
|
||||
Slug: "app",
|
||||
DisplayName: "App",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ProvisionApply: []*proto.Response{
|
||||
{
|
||||
Type: &proto.Response_Apply{
|
||||
Apply: &proto.ApplyComplete{
|
||||
Resources: []*proto.Resource{
|
||||
{
|
||||
Type: "compute",
|
||||
Name: "main",
|
||||
Agents: []*proto.Agent{
|
||||
{
|
||||
Name: "smith",
|
||||
OperatingSystem: "linux",
|
||||
Architecture: "i386",
|
||||
Apps: []*proto.App{
|
||||
{
|
||||
Slug: "app",
|
||||
DisplayName: "App",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user