-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Expand file tree
/
Copy pathboundary_logs_test.go
More file actions
107 lines (93 loc) · 3.72 KB
/
Copy pathboundary_logs_test.go
File metadata and controls
107 lines (93 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package coderd_test
import (
"context"
"sync/atomic"
"testing"
"github.com/google/uuid"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/timestamppb"
agentproto "github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbauthz"
"github.com/coder/coder/v2/coderd/database/dbfake"
"github.com/coder/coder/v2/coderd/database/dbtestutil"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/testutil"
)
// TestReportBoundaryLogsAgentRBAC guards against regressions where
// a pre-insert read (e.g. GetBoundarySessionByID) would be silently denied for
// agents and prevent session creation.
func TestReportBoundaryLogsAgentRBAC(t *testing.T) {
t.Parallel()
store, ps := dbtestutil.NewDB(t)
client := coderdtest.New(t, &coderdtest.Options{Database: store, Pubsub: ps})
user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, store, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
ctx := testutil.Context(t, testutil.WaitLong)
// Connect as a real workspace agent.
ac := agentsdk.New(client.URL, agentsdk.WithFixedToken(r.AgentToken))
conn, err := ac.ConnectRPC(ctx)
require.NoError(t, err)
defer conn.Close()
agentClient := agentproto.NewDRPCAgentClient(conn)
sessionID := uuid.New()
_, err = agentClient.ReportBoundaryLogs(ctx, &agentproto.ReportBoundaryLogsRequest{
SessionId: sessionID.String(),
ConfinedProcessName: "claude-code",
Logs: []*agentproto.BoundaryLog{
{
Allowed: true,
Time: timestamppb.New(dbtime.Now()),
SequenceNumber: 0,
Resource: &agentproto.BoundaryLog_HttpRequest_{
HttpRequest: &agentproto.BoundaryLog_HttpRequest{
Method: "GET",
Url: "https://example.com",
MatchedRule: "domain=example.com",
},
},
},
},
})
require.NoError(t, err)
// Verify persistence via the raw store: because ReportBoundaryLogs swallows
// DB errors and returns success regardless, only a direct read proves the
// session and log were actually persisted under agent RBAC.
sess, err := store.GetBoundarySessionByID(ctx, sessionID)
require.NoError(t, err, "session must be persisted")
require.Equal(t, r.Agents[0].ID, sess.WorkspaceAgentID)
logs, err := store.ListBoundaryLogsBySessionID(ctx, database.ListBoundaryLogsBySessionIDParams{
SessionID: sessionID,
})
require.NoError(t, err)
require.Len(t, logs, 1, "log must be persisted")
// Assert that the agent subject cannot read boundary sessions.
memberRole, err := rbac.RoleByName(rbac.RoleMember())
require.NoError(t, err)
agentSubject := rbac.Subject{
ID: r.Workspace.OwnerID.String(),
Roles: rbac.Roles{memberRole},
Scope: rbac.WorkspaceAgentScope(rbac.WorkspaceAgentScopeParams{
WorkspaceID: r.Workspace.ID,
OwnerID: r.Workspace.OwnerID,
TemplateID: r.Workspace.TemplateID,
VersionID: r.Build.TemplateVersionID,
}),
}.WithCachedASTValue()
auth := rbac.NewStrictCachingAuthorizer(prometheus.NewRegistry())
acsPtr := &atomic.Pointer[dbauthz.AccessControlStore]{}
var acs dbauthz.AccessControlStore = dbauthz.AGPLTemplateAccessControlStore{}
acsPtr.Store(&acs)
authzStore := dbauthz.New(store, auth, testutil.Logger(t), acsPtr)
agentCtx := dbauthz.As(context.Background(), agentSubject)
_, err = authzStore.GetBoundarySessionByID(agentCtx, sessionID)
require.True(t, dbauthz.IsNotAuthorizedError(err),
"agents must not be able to read boundary sessions, got: %v", err)
}