fix(coderd): add stricter authorization for provisioners endpoint (#16587)

References #16558
This commit is contained in:
Mathias Fredriksson
2025-02-17 14:34:47 +02:00
committed by GitHub
parent fbea757b8b
commit 7f061b9faf
4 changed files with 23 additions and 10 deletions
+5 -4
View File
@@ -71,7 +71,7 @@ func TestProvisioners_Golden(t *testing.T) {
})
owner := coderdtest.CreateFirstUser(t, client)
templateAdminClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.ScopedRoleOrgTemplateAdmin(owner.OrganizationID))
memberClient, member := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
_, member := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
// Create initial resources with a running provisioner.
firstProvisioner := coderdtest.NewTaggedProvisionerDaemon(t, coderdAPI, "default-provisioner", map[string]string{"owner": "", "scope": "organization"})
@@ -178,8 +178,9 @@ func TestProvisioners_Golden(t *testing.T) {
t.Logf("replace[%q] = %q", id, replaceID)
}
// Test provisioners list with member as members can access
// provisioner daemons.
// Test provisioners list with template admin as members are currently
// unable to access provisioner jobs. In the future (with RBAC
// changes), we may allow them to view _their_ jobs.
t.Run("list", func(t *testing.T) {
t.Parallel()
@@ -190,7 +191,7 @@ func TestProvisioners_Golden(t *testing.T) {
"--column", "id,created at,last seen at,name,version,tags,key name,status,current job id,current job status,previous job id,previous job status,organization",
)
inv.Stdout = &got
clitest.SetupConfig(t, memberClient, root)
clitest.SetupConfig(t, templateAdminClient, root)
err := inv.Run()
require.NoError(t, err)
+9
View File
@@ -9,6 +9,8 @@ import (
"github.com/coder/coder/v2/coderd/httpapi"
"github.com/coder/coder/v2/coderd/httpmw"
"github.com/coder/coder/v2/coderd/provisionerdserver"
"github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/coderd/rbac/policy"
"github.com/coder/coder/v2/coderd/util/ptr"
"github.com/coder/coder/v2/codersdk"
)
@@ -31,6 +33,13 @@ func (api *API) provisionerDaemons(rw http.ResponseWriter, r *http.Request) {
org = httpmw.OrganizationParam(r)
)
// This endpoint returns information about provisioner jobs.
// For now, only owners and template admins can access provisioner jobs.
if !api.Authorize(r, policy.ActionRead, rbac.ResourceProvisionerJobs.InOrg(org.ID)) {
httpapi.ResourceNotFound(rw)
return
}
qp := r.URL.Query()
p := httpapi.NewQueryParamParser()
limit := p.PositiveInt32(qp, 50, "limit")
+6 -3
View File
@@ -241,11 +241,14 @@ func TestProvisionerDaemons(t *testing.T) {
require.Nil(t, daemons[0].PreviousJob)
})
t.Run("MemberAllowed", func(t *testing.T) {
// For now, this is not allowed even though the member has created a
// workspace. Once member-level permissions for jobs are supported
// by RBAC, this test should be updated.
t.Run("MemberDenied", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitMedium)
daemons, err := memberClient.OrganizationProvisionerDaemons(ctx, owner.OrganizationID, nil)
require.NoError(t, err)
require.Len(t, daemons, 50)
require.Error(t, err)
require.Len(t, daemons, 0)
})
}
+3 -3
View File
@@ -953,7 +953,7 @@ func TestGetProvisionerDaemons(t *testing.T) {
org := coderdenttest.CreateOrganization(t, client, coderdenttest.CreateOrganizationOptions{
IncludeProvisionerDaemon: false,
})
orgAdmin, _ := coderdtest.CreateAnotherUser(t, client, org.ID, rbac.ScopedRoleOrgMember(org.ID))
orgTemplateAdmin, _ := coderdtest.CreateAnotherUser(t, client, org.ID, rbac.ScopedRoleOrgTemplateAdmin(org.ID))
daemonCreatedAt := time.Now()
@@ -986,11 +986,11 @@ func TestGetProvisionerDaemons(t *testing.T) {
require.NoError(t, err, "should be able to create provisioner daemon")
daemonAsCreated := db2sdk.ProvisionerDaemon(pd)
allDaemons, err := orgAdmin.OrganizationProvisionerDaemons(ctx, org.ID, nil)
allDaemons, err := orgTemplateAdmin.OrganizationProvisionerDaemons(ctx, org.ID, nil)
require.NoError(t, err)
require.Len(t, allDaemons, 1)
daemonsAsFound, err := orgAdmin.OrganizationProvisionerDaemons(ctx, org.ID, &codersdk.OrganizationProvisionerDaemonsOptions{
daemonsAsFound, err := orgTemplateAdmin.OrganizationProvisionerDaemons(ctx, org.ID, &codersdk.OrganizationProvisionerDaemonsOptions{
Tags: tt.tagsToFilterBy,
})
if tt.expectToGetDaemon {