Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3fbbaa7

Browse files
committed
fix: Users that can update a template can also read the file
This currently has a strange RBAC story. An issue will be filed to streamline this. This is a hotfix to resolve current functionality
1 parent 88e24db commit 3fbbaa7

File tree

7 files changed

+202
-2
lines changed

7 files changed

+202
-2
lines changed

coderd/database/dbauthz/querier.go

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,57 @@ func (q *querier) GetAuditLogsOffset(ctx context.Context, arg database.GetAuditL
8888
}
8989

9090
func (q *querier) GetFileByHashAndCreator(ctx context.Context, arg database.GetFileByHashAndCreatorParams) (database.File, error) {
91-
return fetch(q.log, q.auth, q.db.GetFileByHashAndCreator)(ctx, arg)
91+
file, err := q.db.GetFileByHashAndCreator(ctx, arg)
92+
if err != nil {
93+
return database.File{}, err
94+
}
95+
err = q.authorizeContext(ctx, rbac.ActionRead, file)
96+
if err != nil {
97+
// Check the user's access to the file's templates.
98+
if q.authorizeReadFile(ctx, file) != nil {
99+
return database.File{}, err
100+
}
101+
}
102+
103+
return file, nil
92104
}
93105

94106
func (q *querier) GetFileByID(ctx context.Context, id uuid.UUID) (database.File, error) {
95-
return fetch(q.log, q.auth, q.db.GetFileByID)(ctx, id)
107+
file, err := q.db.GetFileByID(ctx, id)
108+
if err != nil {
109+
return database.File{}, err
110+
}
111+
err = q.authorizeContext(ctx, rbac.ActionRead, file)
112+
if err != nil {
113+
// Check the user's access to the file's templates.
114+
if q.authorizeUpdateFileTemplate(ctx, file) != nil {
115+
return database.File{}, err
116+
}
117+
}
118+
119+
return file, nil
120+
}
121+
122+
// authorizeReadFile is a hotfix for the fact that file permissions are
123+
// independent of template permissions. This function checks if the user has
124+
// update access to any of the file's templates.
125+
func (q *querier) authorizeUpdateFileTemplate(ctx context.Context, file database.File) error {
126+
tpls, err := q.GetFileTemplates(AsSystemRestricted(ctx), file.ID)
127+
if err != nil {
128+
return err
129+
}
130+
// There __should__ only be 1 template per file, but there can be more than
131+
// 1, so check them all.
132+
for _, tpl := range tpls {
133+
// If the user has update access to any template, they have read access to the file.
134+
if err := q.authorizeContext(ctx, rbac.ActionUpdate, tpl); err == nil {
135+
return nil
136+
}
137+
}
138+
139+
return NotAuthorizedError{
140+
Err: xerrors.Errorf("not authorized to read file %s", file.ID),
141+
}
96142
}
97143

98144
func (q *querier) InsertFile(ctx context.Context, arg database.InsertFileParams) (database.File, error) {

coderd/database/dbauthz/system.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ import (
1010
"github.com/coder/coder/coderd/rbac"
1111
)
1212

13+
func (q *querier) GetFileTemplates(ctx context.Context, fileID uuid.UUID) ([]database.GetFileTemplatesRow, error) {
14+
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
15+
return nil, err
16+
}
17+
return q.db.GetFileTemplates(ctx, fileID)
18+
}
19+
1320
// GetWorkspaceAppsByAgentIDs
1421
// The workspace/job is already fetched.
1522
func (q *querier) GetWorkspaceAppsByAgentIDs(ctx context.Context, ids []uuid.UUID) ([]database.WorkspaceApp, error) {

coderd/database/dbfake/databasefake.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,47 @@ func (q *fakeQuerier) GetFileByID(_ context.Context, id uuid.UUID) (database.Fil
685685
return database.File{}, sql.ErrNoRows
686686
}
687687

688+
func (q *fakeQuerier) GetFileTemplates(_ context.Context, id uuid.UUID) ([]database.GetFileTemplatesRow, error) {
689+
q.mutex.RLock()
690+
defer q.mutex.RUnlock()
691+
692+
rows := make([]database.GetFileTemplatesRow, 0)
693+
var file database.File
694+
for _, f := range q.files {
695+
if f.ID == id {
696+
file = f
697+
break
698+
}
699+
}
700+
if file.Hash == "" {
701+
return rows, nil
702+
}
703+
704+
for _, job := range q.provisionerJobs {
705+
if job.FileID == id {
706+
for _, version := range q.templateVersions {
707+
if version.JobID == job.ID {
708+
for _, template := range q.templates {
709+
if template.ID == version.TemplateID.UUID {
710+
rows = append(rows, database.GetFileTemplatesRow{
711+
FileID: file.ID,
712+
FileCreatedBy: file.CreatedBy,
713+
TemplateID: template.ID,
714+
TemplateOrganizationID: template.OrganizationID,
715+
TemplateCreatedBy: template.CreatedBy,
716+
UserACL: template.UserACL,
717+
GroupACL: template.GroupACL,
718+
})
719+
}
720+
}
721+
}
722+
}
723+
}
724+
}
725+
726+
return rows, sql.ErrNoRows
727+
}
728+
688729
func (q *fakeQuerier) GetUserByEmailOrUsername(_ context.Context, arg database.GetUserByEmailOrUsernameParams) (database.User, error) {
689730
if err := validateDatabaseType(arg); err != nil {
690731
return database.User{}, err

coderd/database/modelmethods.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ func (t Template) RBACObject() rbac.Object {
8888
WithGroupACL(t.GroupACL)
8989
}
9090

91+
func (t GetFileTemplatesRow) RBACObject() rbac.Object {
92+
return rbac.ResourceTemplate.WithID(t.TemplateID).
93+
InOrg(t.TemplateOrganizationID).
94+
WithACLUserList(t.UserACL).
95+
WithGroupACL(t.GroupACL)
96+
}
97+
9198
func (t Template) DeepCopy() Template {
9299
cpy := t
93100
cpy.UserACL = maps.Clone(t.UserACL)

coderd/database/querier.go

Lines changed: 2 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: 69 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/files.sql

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,31 @@ INSERT INTO
2626
files (id, hash, created_at, created_by, mimetype, "data")
2727
VALUES
2828
($1, $2, $3, $4, $5, $6) RETURNING *;
29+
30+
-- name: GetFileTemplates :many
31+
-- Get all templates that use a file.
32+
SELECT
33+
files.id AS file_id,
34+
files.created_by AS file_created_by,
35+
templates.id AS template_id,
36+
templates.organization_id AS template_organization_id,
37+
templates.created_by AS template_created_by,
38+
templates.user_acl,
39+
templates.group_acl
40+
FROM
41+
templates
42+
INNER JOIN
43+
template_versions
44+
ON templates.id = template_versions.template_id
45+
INNER JOIN
46+
provisioner_jobs
47+
ON job_id = provisioner_jobs.id
48+
INNER JOIN
49+
files
50+
ON files.id = provisioner_jobs.file_id
51+
WHERE
52+
-- Only fetch template version associated files.
53+
storage_method = 'file'
54+
AND provisioner_jobs.type = 'template_version_import'
55+
AND file_id = @file_id
56+
;

0 commit comments

Comments
 (0)