Skip to content

Commit f96ce80

Browse files
authored
feat: add owner groups to workspace data (#12841)
1 parent c4b26f3 commit f96ce80

File tree

16 files changed

+323
-130
lines changed

16 files changed

+323
-130
lines changed

coderd/database/dbauthz/dbauthz.go

+5
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ var (
174174
// When org scoped provisioner credentials are implemented,
175175
// this can be reduced to read a specific org.
176176
rbac.ResourceOrganization.Type: {rbac.ActionRead},
177+
rbac.ResourceGroup.Type: {rbac.ActionRead},
177178
}),
178179
Org: map[string][]rbac.Permission{},
179180
User: []rbac.Permission{},
@@ -1141,6 +1142,10 @@ func (q *querier) GetGroupMembers(ctx context.Context, id uuid.UUID) ([]database
11411142
return q.db.GetGroupMembers(ctx, id)
11421143
}
11431144

1145+
func (q *querier) GetGroupsByOrganizationAndUserID(ctx context.Context, arg database.GetGroupsByOrganizationAndUserIDParams) ([]database.Group, error) {
1146+
return fetchWithPostFilter(q.auth, q.db.GetGroupsByOrganizationAndUserID)(ctx, arg)
1147+
}
1148+
11441149
func (q *querier) GetGroupsByOrganizationID(ctx context.Context, organizationID uuid.UUID) ([]database.Group, error) {
11451150
return fetchWithPostFilter(q.auth, q.db.GetGroupsByOrganizationID)(ctx, organizationID)
11461151
}

coderd/database/dbauthz/dbauthz_test.go

+8
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,14 @@ func (s *MethodTestSuite) TestGroup() {
314314
_ = dbgen.GroupMember(s.T(), db, database.GroupMember{})
315315
check.Args(g.ID).Asserts(g, rbac.ActionRead)
316316
}))
317+
s.Run("GetGroupsByOrganizationAndUserID", s.Subtest(func(db database.Store, check *expects) {
318+
g := dbgen.Group(s.T(), db, database.Group{})
319+
gm := dbgen.GroupMember(s.T(), db, database.GroupMember{GroupID: g.ID})
320+
check.Args(database.GetGroupsByOrganizationAndUserIDParams{
321+
OrganizationID: g.OrganizationID,
322+
UserID: gm.UserID,
323+
}).Asserts(g, rbac.ActionRead)
324+
}))
317325
s.Run("InsertAllUsersGroup", s.Subtest(func(db database.Store, check *expects) {
318326
o := dbgen.Organization(s.T(), db, database.Organization{})
319327
check.Args(o.ID).Asserts(rbac.ResourceGroup.InOrg(o.ID), rbac.ActionCreate)

coderd/database/dbmem/dbmem.go

+24
Original file line numberDiff line numberDiff line change
@@ -2250,6 +2250,30 @@ func (q *FakeQuerier) GetGroupMembers(_ context.Context, id uuid.UUID) ([]databa
22502250
return users, nil
22512251
}
22522252

2253+
func (q *FakeQuerier) GetGroupsByOrganizationAndUserID(_ context.Context, arg database.GetGroupsByOrganizationAndUserIDParams) ([]database.Group, error) {
2254+
err := validateDatabaseType(arg)
2255+
if err != nil {
2256+
return nil, err
2257+
}
2258+
2259+
q.mutex.RLock()
2260+
defer q.mutex.RUnlock()
2261+
var groupIds []uuid.UUID
2262+
for _, member := range q.groupMembers {
2263+
if member.UserID == arg.UserID {
2264+
groupIds = append(groupIds, member.GroupID)
2265+
}
2266+
}
2267+
groups := []database.Group{}
2268+
for _, group := range q.groups {
2269+
if slices.Contains(groupIds, group.ID) && group.OrganizationID == arg.OrganizationID {
2270+
groups = append(groups, group)
2271+
}
2272+
}
2273+
2274+
return groups, nil
2275+
}
2276+
22532277
func (q *FakeQuerier) GetGroupsByOrganizationID(_ context.Context, id uuid.UUID) ([]database.Group, error) {
22542278
q.mutex.RLock()
22552279
defer q.mutex.RUnlock()

coderd/database/dbmetrics/dbmetrics.go

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbmock/dbmock.go

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/querier.go

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

+61
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/groups.sql

+25
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,31 @@ FROM
2828
WHERE
2929
organization_id = $1;
3030

31+
-- name: GetGroupsByOrganizationAndUserID :many
32+
SELECT
33+
groups.*
34+
FROM
35+
groups
36+
-- If the group is a user made group, then we need to check the group_members table.
37+
LEFT JOIN
38+
group_members
39+
ON
40+
group_members.group_id = groups.id AND
41+
group_members.user_id = @user_id
42+
-- If it is the "Everyone" group, then we need to check the organization_members table.
43+
LEFT JOIN
44+
organization_members
45+
ON
46+
organization_members.organization_id = groups.id AND
47+
organization_members.user_id = @user_id
48+
WHERE
49+
-- In either case, the group_id will only match an org or a group.
50+
(group_members.user_id = @user_id OR organization_members.user_id = @user_id)
51+
AND
52+
-- Ensure the group or organization is the specified organization.
53+
groups.organization_id = @organization_id;
54+
55+
3156
-- name: InsertGroup :one
3257
INSERT INTO groups (
3358
id,

coderd/provisionerdserver/provisionerdserver.go

+12
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,17 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
467467
if err != nil {
468468
return nil, failJob(fmt.Sprintf("get owner: %s", err))
469469
}
470+
ownerGroups, err := s.Database.GetGroupsByOrganizationAndUserID(ctx, database.GetGroupsByOrganizationAndUserIDParams{
471+
UserID: owner.ID,
472+
OrganizationID: s.OrganizationID,
473+
})
474+
if err != nil {
475+
return nil, failJob(fmt.Sprintf("get owner group names: %s", err))
476+
}
477+
ownerGroupNames := []string{}
478+
for _, group := range ownerGroups {
479+
ownerGroupNames = append(ownerGroupNames, group.Name)
480+
}
470481
err = s.Pubsub.Publish(codersdk.WorkspaceNotifyChannel(workspace.ID), []byte{})
471482
if err != nil {
472483
return nil, failJob(fmt.Sprintf("publish workspace update: %s", err))
@@ -567,6 +578,7 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo
567578
WorkspaceOwner: owner.Username,
568579
WorkspaceOwnerEmail: owner.Email,
569580
WorkspaceOwnerName: owner.Name,
581+
WorkspaceOwnerGroups: ownerGroupNames,
570582
WorkspaceOwnerOidcAccessToken: workspaceOwnerOIDCAccessToken,
571583
WorkspaceId: workspace.ID.String(),
572584
WorkspaceOwnerId: owner.ID.String(),

coderd/provisionerdserver/provisionerdserver_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ func TestAcquireJob(t *testing.T) {
182182
defer cancel()
183183

184184
user := dbgen.User(t, db, database.User{})
185+
group1 := dbgen.Group(t, db, database.Group{
186+
Name: "group1",
187+
OrganizationID: pd.OrganizationID,
188+
})
189+
err := db.InsertGroupMember(ctx, database.InsertGroupMemberParams{
190+
UserID: user.ID,
191+
GroupID: group1.ID,
192+
})
193+
require.NoError(t, err)
185194
link := dbgen.UserLink(t, db, database.UserLink{
186195
LoginType: database.LoginTypeOIDC,
187196
UserID: user.ID,
@@ -340,6 +349,7 @@ func TestAcquireJob(t *testing.T) {
340349
WorkspaceOwnerEmail: user.Email,
341350
WorkspaceOwnerName: user.Name,
342351
WorkspaceOwnerOidcAccessToken: link.OAuthAccessToken,
352+
WorkspaceOwnerGroups: []string{group1.Name},
343353
WorkspaceId: workspace.ID.String(),
344354
WorkspaceOwnerId: user.ID.String(),
345355
TemplateId: template.ID.String(),

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ require (
104104
github.com/coder/flog v1.1.0
105105
github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0
106106
github.com/coder/retry v1.5.1
107-
github.com/coder/terraform-provider-coder v0.19.0
107+
github.com/coder/terraform-provider-coder v0.20.1
108108
github.com/coder/wgtunnel v0.1.13-0.20231127054351-578bfff9b92a
109109
github.com/coreos/go-oidc/v3 v3.10.0
110110
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,8 @@ github.com/coder/ssh v0.0.0-20231128192721-70855dedb788 h1:YoUSJ19E8AtuUFVYBpXuO
217217
github.com/coder/ssh v0.0.0-20231128192721-70855dedb788/go.mod h1:aGQbuCLyhRLMzZF067xc84Lh7JDs1FKwCmF1Crl9dxQ=
218218
github.com/coder/tailscale v1.1.1-0.20240401202854-d329bbdb530d h1:IMvBC1GrCIiZFxpOYRQacZtdjnmsdWNAMilPz+kvdG4=
219219
github.com/coder/tailscale v1.1.1-0.20240401202854-d329bbdb530d/go.mod h1:L8tPrwSi31RAMEMV8rjb0vYTGs7rXt8rAHbqY/p41j4=
220-
github.com/coder/terraform-provider-coder v0.19.0 h1:mmUXSXcar1h2wgwoHIUwdEKy9Kw0GW7fLO4Vzzf+4R4=
221-
github.com/coder/terraform-provider-coder v0.19.0/go.mod h1:pACHRoXSHBGyY696mLeQ1hR/Ag1G2wFk5bw0mT5Zp2g=
220+
github.com/coder/terraform-provider-coder v0.20.1 h1:hz0yvDl8rDJyDgUlFH8QrGUxFKrwmyAQpOhaoTMEmtY=
221+
github.com/coder/terraform-provider-coder v0.20.1/go.mod h1:pACHRoXSHBGyY696mLeQ1hR/Ag1G2wFk5bw0mT5Zp2g=
222222
github.com/coder/wgtunnel v0.1.13-0.20231127054351-578bfff9b92a h1:KhR9LUVllMZ+e9lhubZ1HNrtJDgH5YLoTvpKwmrGag4=
223223
github.com/coder/wgtunnel v0.1.13-0.20231127054351-578bfff9b92a/go.mod h1:QzfptVUdEO+XbkzMKx1kw13i9wwpJlfI1RrZ6SNZ0hA=
224224
github.com/coder/wireguard-go v0.0.0-20230807234434-d825b45ccbf5 h1:eDk/42Kj4xN4yfE504LsvcFEo3dWUiCOaBiWJ2uIH2A=

provisioner/terraform/provision.go

+8
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ package terraform
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
67
"os"
78
"strings"
89
"time"
910

1011
"github.com/spf13/afero"
12+
"golang.org/x/xerrors"
1113

1214
"cdr.dev/slog"
1315
"github.com/coder/terraform-provider-coder/provider"
@@ -186,6 +188,11 @@ func provisionEnv(
186188
richParams []*proto.RichParameterValue, externalAuth []*proto.ExternalAuthProvider,
187189
) ([]string, error) {
188190
env := safeEnviron()
191+
ownerGroups, err := json.Marshal(metadata.GetWorkspaceOwnerGroups())
192+
if err != nil {
193+
return nil, xerrors.Errorf("marshal owner groups: %w", err)
194+
}
195+
189196
env = append(env,
190197
"CODER_AGENT_URL="+metadata.GetCoderUrl(),
191198
"CODER_WORKSPACE_TRANSITION="+strings.ToLower(metadata.GetWorkspaceTransition().String()),
@@ -194,6 +201,7 @@ func provisionEnv(
194201
"CODER_WORKSPACE_OWNER_EMAIL="+metadata.GetWorkspaceOwnerEmail(),
195202
"CODER_WORKSPACE_OWNER_NAME="+metadata.GetWorkspaceOwnerName(),
196203
"CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN="+metadata.GetWorkspaceOwnerOidcAccessToken(),
204+
"CODER_WORKSPACE_OWNER_GROUPS="+string(ownerGroups),
197205
"CODER_WORKSPACE_ID="+metadata.GetWorkspaceId(),
198206
"CODER_WORKSPACE_OWNER_ID="+metadata.GetWorkspaceOwnerId(),
199207
"CODER_WORKSPACE_OWNER_SESSION_TOKEN="+metadata.GetWorkspaceOwnerSessionToken(),

0 commit comments

Comments
 (0)