fix(coderd): scope provisioner module file downloads to the daemon's … · coder/coder@d6ea2bd · GitHub
Skip to content

Commit d6ea2bd

Browse files
fix(coderd): scope provisioner module file downloads to the daemon's org (#26635) (#27883)
Backport of #26635 Original PR: #26635 — fix(coderd): scope provisioner module file downloads to the daemon's org Merge commit: 1961908 Requested by: @jdomeracki-coder <details> <summary>Conflict resolution notes</summary> The cherry-pick conflicted in generated database files because the new `HasTemplateVersionsUsingCachedModuleFileInOrg` query sits adjacent to chatd methods (`HydrateAgentChatsContext`, `IncrementChatGenerationAttempt`) that do not exist on `release/2.34`. Resolved by keeping only the new query and its generated bindings in `querier.go`, `dbmetrics/querymetrics.go`, `dbmock/dbmock.go`, and `dbauthz/dbauthz.go`, then running `gofmt`. Affected packages (`./coderd/database/...`, `./coderd/provisionerdserver/...`) build successfully. </details> --- _Opened by Coder Agents on behalf of @jdomeracki-coder._ --------- Co-authored-by: Jon Ayers <jon@coder.com>
1 parent d70055a commit d6ea2bd

9 files changed

Lines changed: 246 additions & 0 deletions

File tree

coderd/database/dbauthz/dbauthz.go

Lines changed: 10 additions & 0 deletions

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2442,6 +2442,11 @@ func (s *MethodTestSuite) TestTemplate() {
24422442
dbm.EXPECT().GetTemplateVersionTerraformValues(gomock.Any(), tv.ID).Return(val, nil).AnyTimes()
24432443
check.Args(tv.ID).Asserts(t, policy.ActionRead)
24442444
}))
2445+
s.Run("HasTemplateVersionsUsingCachedModuleFileInOrg", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
2446+
arg := database.HasTemplateVersionsUsingCachedModuleFileInOrgParams{FileID: uuid.New(), OrganizationID: uuid.New()}
2447+
dbm.EXPECT().HasTemplateVersionsUsingCachedModuleFileInOrg(gomock.Any(), arg).Return(true, nil).AnyTimes()
2448+
check.Args(arg).Asserts(rbac.ResourceFile.InOrg(arg.OrganizationID), policy.ActionRead).Returns(true)
2449+
}))
24452450
s.Run("GetTemplateVersionVariables", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
24462451
t1 := testutil.Fake(s.T(), faker, database.Template{})
24472452
tv := testutil.Fake(s.T(), faker, database.TemplateVersion{TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}})

coderd/database/dbmetrics/querymetrics.go

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbmock/dbmock.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/querier.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/templateversionterraformvalues.sql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,17 @@ VALUES
2323
@updated_at,
2424
@provisionerd_version
2525
);
26+
27+
-- name: HasTemplateVersionsUsingCachedModuleFileInOrg :one
28+
-- Reports whether the given file is referenced as cached module files by any
29+
-- template version in the given organization. Used to authorize provisioner
30+
-- module-file downloads so a daemon cannot read another organization's cached
31+
-- Terraform module source.
32+
SELECT EXISTS (
33+
SELECT 1
34+
FROM template_version_terraform_values tvtv
35+
JOIN template_versions tv
36+
ON tv.id = tvtv.template_version_id
37+
WHERE tvtv.cached_module_files = @file_id::uuid
38+
AND tv.organization_id = @organization_id::uuid
39+
);

coderd/provisionerdserver/provisionerdserver.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,26 @@ func (s *server) DownloadFile(request *proto.FileRequest, stream proto.DRPCProvi
15841584
if file.CreatedBy != uuid.Nil || file.Mimetype != tarMimeType {
15851585
return fail(xerrors.Errorf("file %s is not a modules file", fid))
15861586
}
1587+
// Ensure the requested module file belongs to a template version in
1588+
// this provisioner daemon's organization. Without this, any
1589+
// authenticated provisioner could download cached module archives
1590+
// (Terraform source) belonging to other organizations (ANT-2026-22440).
1591+
ok, err := s.Database.HasTemplateVersionsUsingCachedModuleFileInOrg(ctx, database.HasTemplateVersionsUsingCachedModuleFileInOrgParams{
1592+
FileID: fid,
1593+
OrganizationID: s.OrganizationID,
1594+
})
1595+
if err != nil {
1596+
return fail(xerrors.Errorf("authorize module file: %w", err))
1597+
}
1598+
if !ok {
1599+
s.Logger.Warn(ctx, "module file download rejected: file not referenced by any template version in daemon org",
1600+
slog.F("file_id", fid),
1601+
slog.F("organization_id", s.OrganizationID),
1602+
)
1603+
// Use the same error as the metadata check above so the handler
1604+
// does not confirm the existence of files in other organizations.
1605+
return fail(xerrors.Errorf("file %s is not a modules file", fid))
1606+
}
15871607
default:
15881608
return fail(xerrors.Errorf("unsupported file upload type: %s", request.UploadType))
15891609
}

coderd/provisionerdserver/provisionerdserver_test.go

Lines changed: 142 additions & 0 deletions

0 commit comments

Comments
 (0)