Skip to content

Commit 0374e11

Browse files
committed
Merge branch 'main' of https://github.com/coder/coder into bq/refactor-web-term-notifications
2 parents 47a88f7 + 23ff807 commit 0374e11

File tree

646 files changed

+3089
-2681
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

646 files changed

+3089
-2681
lines changed

.github/workflows/security.yaml

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ jobs:
2828
- name: Checkout
2929
uses: actions/checkout@v4
3030

31+
- name: Setup Go
32+
uses: ./.github/actions/setup-go
33+
3134
- name: Initialize CodeQL
3235
uses: github/codeql-action/init@v3
3336
with:
3437
languages: go, javascript
3538

36-
- name: Setup Go
37-
uses: ./.github/actions/setup-go
38-
3939
# Workaround to prevent CodeQL from building the dashboard.
4040
- name: Remove Makefile
4141
run: |
@@ -113,14 +113,6 @@ jobs:
113113
make -j "$image_job"
114114
echo "image=$(cat "$image_job")" >> $GITHUB_OUTPUT
115115
116-
- name: Run Prisma Cloud image scan
117-
uses: PaloAltoNetworks/prisma-cloud-scan@v1
118-
with:
119-
pcc_console_url: ${{ secrets.PRISMA_CLOUD_URL }}
120-
pcc_user: ${{ secrets.PRISMA_CLOUD_ACCESS_KEY }}
121-
pcc_pass: ${{ secrets.PRISMA_CLOUD_SECRET_KEY }}
122-
image_name: ${{ steps.build.outputs.image }}
123-
124116
- name: Run Trivy vulnerability scanner
125117
uses: aquasecurity/trivy-action@84384bd6e777ef152729993b8145ea352e9dd3ef
126118
with:
@@ -142,6 +134,16 @@ jobs:
142134
path: trivy-results.sarif
143135
retention-days: 7
144136

137+
# Prisma cloud scan runs last because it fails the entire job if it
138+
# detects vulnerabilities. :|
139+
- name: Run Prisma Cloud image scan
140+
uses: PaloAltoNetworks/prisma-cloud-scan@v1
141+
with:
142+
pcc_console_url: ${{ secrets.PRISMA_CLOUD_URL }}
143+
pcc_user: ${{ secrets.PRISMA_CLOUD_ACCESS_KEY }}
144+
pcc_pass: ${{ secrets.PRISMA_CLOUD_SECRET_KEY }}
145+
image_name: ${{ steps.build.outputs.image }}
146+
145147
- name: Send Slack notification on failure
146148
if: ${{ failure() }}
147149
run: |

Makefile

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -382,32 +382,44 @@ install: build/coder_$(VERSION)_$(GOOS)_$(GOARCH)$(GOOS_BIN_EXT)
382382
cp "$<" "$$output_file"
383383
.PHONY: install
384384

385-
fmt: fmt/prettier fmt/terraform fmt/shfmt fmt/go
385+
BOLD := $(shell tput bold)
386+
GREEN := $(shell tput setaf 2)
387+
RESET := $(shell tput sgr0)
388+
389+
fmt: fmt/eslint fmt/prettier fmt/terraform fmt/shfmt fmt/go
386390
.PHONY: fmt
387391

388392
fmt/go:
393+
echo "$(GREEN)==>$(RESET) $(BOLD)fmt/go$(RESET)"
389394
# VS Code users should check out
390395
# https://github.com/mvdan/gofumpt#visual-studio-code
391396
go run mvdan.cc/gofumpt@v0.4.0 -w -l .
392397
.PHONY: fmt/go
393398

399+
fmt/eslint:
400+
echo "$(GREEN)==>$(RESET) $(BOLD)fmt/eslint$(RESET)"
401+
cd site
402+
pnpm run lint:fix
403+
.PHONY: fmt/eslint
404+
394405
fmt/prettier:
395-
echo "--- prettier"
406+
echo "$(GREEN)==>$(RESET) $(BOLD)fmt/prettier$(RESET)"
396407
cd site
397408
# Avoid writing files in CI to reduce file write activity
398409
ifdef CI
399410
pnpm run format:check
400411
else
401-
pnpm run format:write
412+
pnpm run format
402413
endif
403414
.PHONY: fmt/prettier
404415

405416
fmt/terraform: $(wildcard *.tf)
417+
echo "$(GREEN)==>$(RESET) $(BOLD)fmt/terraform$(RESET)"
406418
terraform fmt -recursive
407419
.PHONY: fmt/terraform
408420

409421
fmt/shfmt: $(SHELL_SRC_FILES)
410-
echo "--- shfmt"
422+
echo "$(GREEN)==>$(RESET) $(BOLD)fmt/shfmt$(RESET)"
411423
# Only do diff check in CI, errors on diff.
412424
ifdef CI
413425
shfmt -d $(SHELL_SRC_FILES)
@@ -574,7 +586,7 @@ provisionerd/proto/provisionerd.pb.go: provisionerd/proto/provisionerd.proto
574586

575587
site/src/api/typesGenerated.ts: $(wildcard scripts/apitypings/*) $(shell find ./codersdk $(FIND_EXCLUSIONS) -type f -name '*.go')
576588
go run ./scripts/apitypings/ > $@
577-
pnpm run format:write:only "$@"
589+
pnpm exec prettier --write "$@"
578590

579591
site/e2e/provisionerGenerated.ts: provisionerd/proto/provisionerd.pb.go provisionersdk/proto/provisioner.pb.go
580592
cd site
@@ -583,7 +595,7 @@ site/e2e/provisionerGenerated.ts: provisionerd/proto/provisionerd.pb.go provisio
583595

584596
site/src/theme/icons.json: $(wildcard scripts/gensite/*) $(wildcard site/static/icon/*)
585597
go run ./scripts/gensite/ -icons "$@"
586-
pnpm run format:write:only "$@"
598+
pnpm exec prettier --write "$@"
587599

588600
examples/examples.gen.json: scripts/examplegen/main.go examples/examples.go $(shell find ./examples/templates)
589601
go run ./scripts/examplegen/main.go > examples/examples.gen.json
@@ -593,19 +605,19 @@ coderd/rbac/object_gen.go: scripts/rbacgen/main.go coderd/rbac/object.go
593605

594606
docs/admin/prometheus.md: scripts/metricsdocgen/main.go scripts/metricsdocgen/metrics
595607
go run scripts/metricsdocgen/main.go
596-
pnpm run format:write:only ./docs/admin/prometheus.md
608+
pnpm exec prettier --write ./docs/admin/prometheus.md
597609

598610
docs/cli.md: scripts/clidocgen/main.go examples/examples.gen.json $(GO_SRC_FILES)
599611
CI=true BASE_PATH="." go run ./scripts/clidocgen
600-
pnpm run format:write:only ./docs/cli.md ./docs/cli/*.md ./docs/manifest.json
612+
pnpm exec prettier --write ./docs/cli.md ./docs/cli/*.md ./docs/manifest.json
601613

602614
docs/admin/audit-logs.md: coderd/database/querier.go scripts/auditdocgen/main.go enterprise/audit/table.go coderd/rbac/object_gen.go
603615
go run scripts/auditdocgen/main.go
604-
pnpm run format:write:only ./docs/admin/audit-logs.md
616+
pnpm exec prettier --write ./docs/admin/audit-logs.md
605617

606618
coderd/apidoc/swagger.json: $(shell find ./scripts/apidocgen $(FIND_EXCLUSIONS) -type f) $(wildcard coderd/*.go) $(wildcard enterprise/coderd/*.go) $(wildcard codersdk/*.go) $(wildcard enterprise/wsproxy/wsproxysdk/*.go) $(DB_GEN_FILES) .swaggo docs/manifest.json coderd/rbac/object_gen.go
607619
./scripts/apidocgen/generate.sh
608-
pnpm run format:write:only ./docs/api ./docs/manifest.json ./coderd/apidoc/swagger.json
620+
pnpm exec prettier --write ./docs/api ./docs/manifest.json ./coderd/apidoc/swagger.json
609621

610622
update-golden-files: \
611623
cli/testdata/.gen-golden \

cli/templatelist_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ func TestTemplateList(t *testing.T) {
8787
t.Parallel()
8888
client := coderdtest.New(t, &coderdtest.Options{})
8989
owner := coderdtest.CreateFirstUser(t, client)
90+
91+
org, err := client.Organization(context.Background(), owner.OrganizationID)
92+
require.NoError(t, err)
93+
9094
templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
9195

9296
inv, root := clitest.New(t, "templates", "list")
@@ -107,7 +111,7 @@ func TestTemplateList(t *testing.T) {
107111
require.NoError(t, <-errC)
108112

109113
pty.ExpectMatch("No templates found in")
110-
pty.ExpectMatch(coderdtest.FirstUserParams.Username)
114+
pty.ExpectMatch(org.Name)
111115
pty.ExpectMatch("Create one:")
112116
})
113117
}

coderd/database/dbauthz/dbauthz.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ var (
232232
rbac.ResourceGroup.Type: {rbac.ActionCreate, rbac.ActionUpdate},
233233
rbac.ResourceRoleAssignment.Type: {rbac.ActionCreate, rbac.ActionDelete},
234234
rbac.ResourceSystem.Type: {rbac.WildcardSymbol},
235-
rbac.ResourceOrganization.Type: {rbac.ActionCreate},
235+
rbac.ResourceOrganization.Type: {rbac.ActionCreate, rbac.ActionRead},
236236
rbac.ResourceOrganizationMember.Type: {rbac.ActionCreate},
237237
rbac.ResourceOrgRoleAssignment.Type: {rbac.ActionCreate},
238238
rbac.ResourceProvisionerDaemon.Type: {rbac.ActionCreate, rbac.ActionUpdate},
@@ -915,6 +915,19 @@ func (q *querier) DeleteWorkspaceAgentPortShare(ctx context.Context, arg databas
915915
return q.db.DeleteWorkspaceAgentPortShare(ctx, arg)
916916
}
917917

918+
func (q *querier) DeleteWorkspaceAgentPortSharesByTemplate(ctx context.Context, templateID uuid.UUID) error {
919+
template, err := q.db.GetTemplateByID(ctx, templateID)
920+
if err != nil {
921+
return err
922+
}
923+
924+
if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil {
925+
return err
926+
}
927+
928+
return q.db.DeleteWorkspaceAgentPortSharesByTemplate(ctx, templateID)
929+
}
930+
918931
func (q *querier) FavoriteWorkspace(ctx context.Context, id uuid.UUID) error {
919932
fetch := func(ctx context.Context, id uuid.UUID) (database.Workspace, error) {
920933
return q.db.GetWorkspaceByID(ctx, id)
@@ -2614,6 +2627,19 @@ func (q *querier) ListWorkspaceAgentPortShares(ctx context.Context, workspaceID
26142627
return q.db.ListWorkspaceAgentPortShares(ctx, workspaceID)
26152628
}
26162629

2630+
func (q *querier) ReduceWorkspaceAgentShareLevelToAuthenticatedByTemplate(ctx context.Context, templateID uuid.UUID) error {
2631+
template, err := q.db.GetTemplateByID(ctx, templateID)
2632+
if err != nil {
2633+
return err
2634+
}
2635+
2636+
if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil {
2637+
return err
2638+
}
2639+
2640+
return q.db.ReduceWorkspaceAgentShareLevelToAuthenticatedByTemplate(ctx, templateID)
2641+
}
2642+
26172643
func (q *querier) RegisterWorkspaceProxy(ctx context.Context, arg database.RegisterWorkspaceProxyParams) (database.WorkspaceProxy, error) {
26182644
fetch := func(ctx context.Context, arg database.RegisterWorkspaceProxyParams) (database.WorkspaceProxy, error) {
26192645
return q.db.GetWorkspaceProxyByID(ctx, arg.ID)

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ func (s *MethodTestSuite) TestOrganization() {
568568
check.Args(o.ID).Asserts(o, rbac.ActionRead).Returns(o)
569569
}))
570570
s.Run("GetDefaultOrganization", s.Subtest(func(db database.Store, check *expects) {
571-
o := dbgen.Organization(s.T(), db, database.Organization{})
571+
o, _ := db.GetDefaultOrganization(context.Background())
572572
check.Args().Asserts(o, rbac.ActionRead).Returns(o)
573573
}))
574574
s.Run("GetOrganizationByName", s.Subtest(func(db database.Store, check *expects) {
@@ -597,9 +597,10 @@ func (s *MethodTestSuite) TestOrganization() {
597597
check.Args(u.ID).Asserts(a, rbac.ActionRead, b, rbac.ActionRead).Returns(slice.New(a, b))
598598
}))
599599
s.Run("GetOrganizations", s.Subtest(func(db database.Store, check *expects) {
600+
def, _ := db.GetDefaultOrganization(context.Background())
600601
a := dbgen.Organization(s.T(), db, database.Organization{})
601602
b := dbgen.Organization(s.T(), db, database.Organization{})
602-
check.Args().Asserts(a, rbac.ActionRead, b, rbac.ActionRead).Returns(slice.New(a, b))
603+
check.Args().Asserts(def, rbac.ActionRead, a, rbac.ActionRead, b, rbac.ActionRead).Returns(slice.New(def, a, b))
603604
}))
604605
s.Run("GetOrganizationsByUserID", s.Subtest(func(db database.Store, check *expects) {
605606
u := dbgen.User(s.T(), db, database.User{})
@@ -1635,6 +1636,20 @@ func (s *MethodTestSuite) TestWorkspacePortSharing() {
16351636
Port: ps.Port,
16361637
}).Asserts(ws, rbac.ActionUpdate).Returns()
16371638
}))
1639+
s.Run("DeleteWorkspaceAgentPortSharesByTemplate", s.Subtest(func(db database.Store, check *expects) {
1640+
u := dbgen.User(s.T(), db, database.User{})
1641+
t := dbgen.Template(s.T(), db, database.Template{})
1642+
ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID, TemplateID: t.ID})
1643+
_ = dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID})
1644+
check.Args(t.ID).Asserts(t, rbac.ActionUpdate).Returns()
1645+
}))
1646+
s.Run("ReduceWorkspaceAgentShareLevelToAuthenticatedByTemplate", s.Subtest(func(db database.Store, check *expects) {
1647+
u := dbgen.User(s.T(), db, database.User{})
1648+
t := dbgen.Template(s.T(), db, database.Template{})
1649+
ws := dbgen.Workspace(s.T(), db, database.Workspace{OwnerID: u.ID, TemplateID: t.ID})
1650+
_ = dbgen.WorkspaceAgentPortShare(s.T(), db, database.WorkspaceAgentPortShare{WorkspaceID: ws.ID})
1651+
check.Args(t.ID).Asserts(t, rbac.ActionUpdate).Returns()
1652+
}))
16381653
}
16391654

16401655
func (s *MethodTestSuite) TestExtraMethods() {

coderd/database/dbmem/dbmem.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,17 @@ func New() database.Store {
7777
locks: map[int64]struct{}{},
7878
},
7979
}
80+
// Always start with a default org. Matching migration 198.
81+
_, err := q.InsertOrganization(context.Background(), database.InsertOrganizationParams{
82+
ID: uuid.New(),
83+
Name: "first-organization",
84+
Description: "Builtin default organization.",
85+
CreatedAt: dbtime.Now(),
86+
UpdatedAt: dbtime.Now(),
87+
})
88+
if err != nil {
89+
panic(fmt.Errorf("failed to create default organization: %w", err))
90+
}
8091
q.defaultProxyDisplayName = "Default"
8192
q.defaultProxyIconURL = "/emojis/1f3e1.png"
8293
return q
@@ -1455,6 +1466,30 @@ func (q *FakeQuerier) DeleteWorkspaceAgentPortShare(_ context.Context, arg datab
14551466
return nil
14561467
}
14571468

1469+
func (q *FakeQuerier) DeleteWorkspaceAgentPortSharesByTemplate(_ context.Context, templateID uuid.UUID) error {
1470+
err := validateDatabaseType(templateID)
1471+
if err != nil {
1472+
return err
1473+
}
1474+
1475+
q.mutex.Lock()
1476+
defer q.mutex.Unlock()
1477+
1478+
for _, workspace := range q.workspaces {
1479+
if workspace.TemplateID != templateID {
1480+
continue
1481+
}
1482+
for i, share := range q.workspaceAgentPortShares {
1483+
if share.WorkspaceID != workspace.ID {
1484+
continue
1485+
}
1486+
q.workspaceAgentPortShares = append(q.workspaceAgentPortShares[:i], q.workspaceAgentPortShares[i+1:]...)
1487+
}
1488+
}
1489+
1490+
return nil
1491+
}
1492+
14581493
func (q *FakeQuerier) FavoriteWorkspace(_ context.Context, arg uuid.UUID) error {
14591494
err := validateDatabaseType(arg)
14601495
if err != nil {
@@ -6339,6 +6374,33 @@ func (q *FakeQuerier) ListWorkspaceAgentPortShares(_ context.Context, workspaceI
63396374
return shares, nil
63406375
}
63416376

6377+
func (q *FakeQuerier) ReduceWorkspaceAgentShareLevelToAuthenticatedByTemplate(_ context.Context, templateID uuid.UUID) error {
6378+
err := validateDatabaseType(templateID)
6379+
if err != nil {
6380+
return err
6381+
}
6382+
6383+
q.mutex.Lock()
6384+
defer q.mutex.Unlock()
6385+
6386+
for _, workspace := range q.workspaces {
6387+
if workspace.TemplateID != templateID {
6388+
continue
6389+
}
6390+
for i, share := range q.workspaceAgentPortShares {
6391+
if share.WorkspaceID != workspace.ID {
6392+
continue
6393+
}
6394+
if share.ShareLevel == database.AppSharingLevelPublic {
6395+
share.ShareLevel = database.AppSharingLevelAuthenticated
6396+
}
6397+
q.workspaceAgentPortShares[i] = share
6398+
}
6399+
}
6400+
6401+
return nil
6402+
}
6403+
63426404
func (q *FakeQuerier) RegisterWorkspaceProxy(_ context.Context, arg database.RegisterWorkspaceProxyParams) (database.WorkspaceProxy, error) {
63436405
q.mutex.Lock()
63446406
defer q.mutex.Unlock()

coderd/database/dbmetrics/dbmetrics.go

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

0 commit comments

Comments
 (0)