mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(coderd): scope provisioner module file downloads to the daemon's org (#26635)
This commit is contained in:
@@ -5697,6 +5697,16 @@ func (q *querier) GetWorkspacesForWorkspaceMetrics(ctx context.Context) ([]datab
|
||||
return q.db.GetWorkspacesForWorkspaceMetrics(ctx)
|
||||
}
|
||||
|
||||
func (q *querier) HasTemplateVersionsUsingCachedModuleFileInOrg(ctx context.Context, arg database.HasTemplateVersionsUsingCachedModuleFileInOrgParams) (bool, error) {
|
||||
// This query authorizes provisioner module-file downloads. The caller
|
||||
// must be able to read files in the target organization; the actual
|
||||
// tenant isolation comes from the organization_id filter in the query.
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceFile.InOrg(arg.OrganizationID)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return q.db.HasTemplateVersionsUsingCachedModuleFileInOrg(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) HydrateAgentChatsContext(ctx context.Context, arg database.HydrateAgentChatsContextParams) error {
|
||||
// System-level operation: an agent context push fans hydration out
|
||||
// across every not-yet-pinned chat for the agent, so it authorizes at
|
||||
|
||||
@@ -2674,6 +2674,11 @@ func (s *MethodTestSuite) TestTemplate() {
|
||||
dbm.EXPECT().GetTemplateVersionTerraformValues(gomock.Any(), tv.ID).Return(val, nil).AnyTimes()
|
||||
check.Args(tv.ID).Asserts(t, policy.ActionRead)
|
||||
}))
|
||||
s.Run("HasTemplateVersionsUsingCachedModuleFileInOrg", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
|
||||
arg := database.HasTemplateVersionsUsingCachedModuleFileInOrgParams{FileID: uuid.New(), OrganizationID: uuid.New()}
|
||||
dbm.EXPECT().HasTemplateVersionsUsingCachedModuleFileInOrg(gomock.Any(), arg).Return(true, nil).AnyTimes()
|
||||
check.Args(arg).Asserts(rbac.ResourceFile.InOrg(arg.OrganizationID), policy.ActionRead).Returns(true)
|
||||
}))
|
||||
s.Run("GetTemplateVersionVariables", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
t1 := testutil.Fake(s.T(), faker, database.Template{})
|
||||
tv := testutil.Fake(s.T(), faker, database.TemplateVersion{TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}})
|
||||
|
||||
+8
@@ -3874,6 +3874,14 @@ func (m queryMetricsStore) GetWorkspacesForWorkspaceMetrics(ctx context.Context)
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) HasTemplateVersionsUsingCachedModuleFileInOrg(ctx context.Context, arg database.HasTemplateVersionsUsingCachedModuleFileInOrgParams) (bool, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.HasTemplateVersionsUsingCachedModuleFileInOrg(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("HasTemplateVersionsUsingCachedModuleFileInOrg").Observe(time.Since(start).Seconds())
|
||||
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "HasTemplateVersionsUsingCachedModuleFileInOrg").Inc()
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) HydrateAgentChatsContext(ctx context.Context, arg database.HydrateAgentChatsContextParams) error {
|
||||
start := time.Now()
|
||||
r0 := m.s.HydrateAgentChatsContext(ctx, arg)
|
||||
|
||||
Generated
+15
@@ -7242,6 +7242,21 @@ func (mr *MockStoreMockRecorder) GetWorkspacesForWorkspaceMetrics(ctx any) *gomo
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkspacesForWorkspaceMetrics", reflect.TypeOf((*MockStore)(nil).GetWorkspacesForWorkspaceMetrics), ctx)
|
||||
}
|
||||
|
||||
// HasTemplateVersionsUsingCachedModuleFileInOrg mocks base method.
|
||||
func (m *MockStore) HasTemplateVersionsUsingCachedModuleFileInOrg(ctx context.Context, arg database.HasTemplateVersionsUsingCachedModuleFileInOrgParams) (bool, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HasTemplateVersionsUsingCachedModuleFileInOrg", ctx, arg)
|
||||
ret0, _ := ret[0].(bool)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// HasTemplateVersionsUsingCachedModuleFileInOrg indicates an expected call of HasTemplateVersionsUsingCachedModuleFileInOrg.
|
||||
func (mr *MockStoreMockRecorder) HasTemplateVersionsUsingCachedModuleFileInOrg(ctx, arg any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasTemplateVersionsUsingCachedModuleFileInOrg", reflect.TypeOf((*MockStore)(nil).HasTemplateVersionsUsingCachedModuleFileInOrg), ctx, arg)
|
||||
}
|
||||
|
||||
// HydrateAgentChatsContext mocks base method.
|
||||
func (m *MockStore) HydrateAgentChatsContext(ctx context.Context, arg database.HydrateAgentChatsContextParams) error {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
Generated
+5
@@ -975,6 +975,11 @@ type sqlcQuerier interface {
|
||||
GetWorkspacesByTemplateID(ctx context.Context, templateID uuid.UUID) ([]WorkspaceTable, error)
|
||||
GetWorkspacesEligibleForTransition(ctx context.Context, now time.Time) ([]GetWorkspacesEligibleForTransitionRow, error)
|
||||
GetWorkspacesForWorkspaceMetrics(ctx context.Context) ([]GetWorkspacesForWorkspaceMetricsRow, error)
|
||||
// Reports whether the given file is referenced as cached module files by any
|
||||
// template version in the given organization. Used to authorize provisioner
|
||||
// module-file downloads so a daemon cannot read another organization's cached
|
||||
// Terraform module source.
|
||||
HasTemplateVersionsUsingCachedModuleFileInOrg(ctx context.Context, arg HasTemplateVersionsUsingCachedModuleFileInOrgParams) (bool, error)
|
||||
// Stamps the pinned hash and error on every not-yet-hydrated chat for
|
||||
// an agent (context_aggregate_hash IS NULL) and copies the agent's
|
||||
// current context resources onto those chats in the same statement, so
|
||||
|
||||
Generated
+27
@@ -27698,6 +27698,33 @@ func (q *sqlQuerier) GetTemplateVersionTerraformValues(ctx context.Context, temp
|
||||
return i, err
|
||||
}
|
||||
|
||||
const hasTemplateVersionsUsingCachedModuleFileInOrg = `-- name: HasTemplateVersionsUsingCachedModuleFileInOrg :one
|
||||
SELECT EXISTS (
|
||||
SELECT 1
|
||||
FROM template_version_terraform_values tvtv
|
||||
JOIN template_versions tv
|
||||
ON tv.id = tvtv.template_version_id
|
||||
WHERE tvtv.cached_module_files = $1::uuid
|
||||
AND tv.organization_id = $2::uuid
|
||||
)
|
||||
`
|
||||
|
||||
type HasTemplateVersionsUsingCachedModuleFileInOrgParams struct {
|
||||
FileID uuid.UUID `db:"file_id" json:"file_id"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
}
|
||||
|
||||
// Reports whether the given file is referenced as cached module files by any
|
||||
// template version in the given organization. Used to authorize provisioner
|
||||
// module-file downloads so a daemon cannot read another organization's cached
|
||||
// Terraform module source.
|
||||
func (q *sqlQuerier) HasTemplateVersionsUsingCachedModuleFileInOrg(ctx context.Context, arg HasTemplateVersionsUsingCachedModuleFileInOrgParams) (bool, error) {
|
||||
row := q.db.QueryRowContext(ctx, hasTemplateVersionsUsingCachedModuleFileInOrg, arg.FileID, arg.OrganizationID)
|
||||
var exists bool
|
||||
err := row.Scan(&exists)
|
||||
return exists, err
|
||||
}
|
||||
|
||||
const insertTemplateVersionTerraformValuesByJobID = `-- name: InsertTemplateVersionTerraformValuesByJobID :exec
|
||||
INSERT INTO
|
||||
template_version_terraform_values (
|
||||
|
||||
@@ -23,3 +23,17 @@ VALUES
|
||||
@updated_at,
|
||||
@provisionerd_version
|
||||
);
|
||||
|
||||
-- name: HasTemplateVersionsUsingCachedModuleFileInOrg :one
|
||||
-- Reports whether the given file is referenced as cached module files by any
|
||||
-- template version in the given organization. Used to authorize provisioner
|
||||
-- module-file downloads so a daemon cannot read another organization's cached
|
||||
-- Terraform module source.
|
||||
SELECT EXISTS (
|
||||
SELECT 1
|
||||
FROM template_version_terraform_values tvtv
|
||||
JOIN template_versions tv
|
||||
ON tv.id = tvtv.template_version_id
|
||||
WHERE tvtv.cached_module_files = @file_id::uuid
|
||||
AND tv.organization_id = @organization_id::uuid
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user