Skip to content

Commit

Permalink
feat: RBAC provisionerdaemons and parameters (#1755)
Browse files Browse the repository at this point in the history
* chore: Remove org_id from provisionerdaemons
  • Loading branch information
Emyrk committed May 26, 2022
1 parent 104d07f commit c04d045
Show file tree
Hide file tree
Showing 18 changed files with 184 additions and 63 deletions.
10 changes: 8 additions & 2 deletions coderd/coderd.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,20 @@ func New(options *Options) *API {
r.Get("/{hash}", api.fileByHash)
r.Post("/", api.postFile)
})
r.Route("/provisionerdaemons", func(r chi.Router) {
r.Use(
apiKeyMiddleware,
authRolesMiddleware,
)
r.Get("/", api.provisionerDaemons)
})
r.Route("/organizations/{organization}", func(r chi.Router) {
r.Use(
apiKeyMiddleware,
httpmw.ExtractOrganizationParam(options.Database),
authRolesMiddleware,
)
r.Get("/", api.organization)
r.Get("/provisionerdaemons", api.provisionerDaemonsByOrganization)
r.Post("/templateversions", api.postTemplateVersionsByOrganization)
r.Route("/templates", func(r chi.Router) {
r.Post("/", api.postTemplateByOrganization)
Expand Down Expand Up @@ -166,7 +172,7 @@ func New(options *Options) *API {
})
})
r.Route("/parameters/{scope}/{id}", func(r chi.Router) {
r.Use(apiKeyMiddleware)
r.Use(apiKeyMiddleware, authRolesMiddleware)
r.Post("/", api.postParameter)
r.Get("/", api.parameters)
r.Route("/{name}", func(r chi.Router) {
Expand Down
64 changes: 51 additions & 13 deletions coderd/coderd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"
"strings"
"testing"
"time"

"github.com/go-chi/chi/v5"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -45,9 +46,29 @@ func TestAuthorizeAllEndpoints(t *testing.T) {
IncludeProvisionerD: true,
})
admin := coderdtest.CreateFirstUser(t, client)
organization, err := client.Organization(context.Background(), admin.OrganizationID)
// The provisioner will call to coderd and register itself. This is async,
// so we wait for it to occur.
require.Eventually(t, func() bool {
provisionerds, err := client.ProvisionerDaemons(ctx)
require.NoError(t, err)
return len(provisionerds) > 0
}, time.Second*10, time.Second)

provisionerds, err := client.ProvisionerDaemons(ctx)
require.NoError(t, err, "fetch provisioners")
require.Len(t, provisionerds, 1)

organization, err := client.Organization(ctx, admin.OrganizationID)
require.NoError(t, err, "fetch org")

organizationParam, err := client.CreateParameter(ctx, codersdk.ParameterOrganization, organization.ID, codersdk.CreateParameterRequest{
Name: "test-param",
SourceValue: "hello world",
SourceScheme: codersdk.ParameterSourceSchemeData,
DestinationScheme: codersdk.ParameterDestinationSchemeProvisionerVariable,
})
require.NoError(t, err, "create org param")

// Setup some data in the database.
version := coderdtest.CreateTemplateVersion(t, client, admin.OrganizationID, &echo.Responses{
Parse: echo.ParseComplete,
Expand Down Expand Up @@ -118,18 +139,10 @@ func TestAuthorizeAllEndpoints(t *testing.T) {
"GET:/api/v2/workspaceagents/{workspaceagent}/turn": {NoAuthorize: true},

// TODO: @emyrk these need to be fixed by adding authorize calls
"GET:/api/v2/organizations/{organization}/provisionerdaemons": {NoAuthorize: true},
"GET:/api/v2/organizations/{organization}/templates/{templatename}": {NoAuthorize: true},
"POST:/api/v2/organizations/{organization}/templateversions": {NoAuthorize: true},
"POST:/api/v2/organizations/{organization}/workspaces": {NoAuthorize: true},

"POST:/api/v2/parameters/{scope}/{id}": {NoAuthorize: true},
"GET:/api/v2/parameters/{scope}/{id}": {NoAuthorize: true},
"DELETE:/api/v2/parameters/{scope}/{id}/{name}": {NoAuthorize: true},

"POST:/api/v2/users/{user}/organizations": {NoAuthorize: true},

"GET:/api/v2/workspaces/{workspace}/watch": {NoAuthorize: true},
"POST:/api/v2/organizations/{organization}/workspaces": {NoAuthorize: true},
"POST:/api/v2/users/{user}/organizations": {NoAuthorize: true},
"GET:/api/v2/workspaces/{workspace}/watch": {NoAuthorize: true},
"POST:/api/v2/organizations/{organization}/templateversions": {NoAuthorize: true},

// These endpoints have more assertions. This is good, add more endpoints to assert if you can!
"GET:/api/v2/organizations/{organization}": {AssertObject: rbac.ResourceOrganization.InOrg(admin.OrganizationID)},
Expand Down Expand Up @@ -251,6 +264,27 @@ func TestAuthorizeAllEndpoints(t *testing.T) {
AssertAction: rbac.ActionRead,
AssertObject: rbac.ResourceTemplate.InOrg(template.OrganizationID).WithID(template.ID.String()),
},
"GET:/api/v2/provisionerdaemons": {
StatusCode: http.StatusOK,
AssertObject: rbac.ResourceProvisionerDaemon.WithID(provisionerds[0].ID.String()),
},

"POST:/api/v2/parameters/{scope}/{id}": {
AssertAction: rbac.ActionUpdate,
AssertObject: rbac.ResourceOrganization.WithID(organization.ID.String()),
},
"GET:/api/v2/parameters/{scope}/{id}": {
AssertAction: rbac.ActionRead,
AssertObject: rbac.ResourceOrganization.WithID(organization.ID.String()),
},
"DELETE:/api/v2/parameters/{scope}/{id}/{name}": {
AssertAction: rbac.ActionUpdate,
AssertObject: rbac.ResourceOrganization.WithID(organization.ID.String()),
},
"GET:/api/v2/organizations/{organization}/templates/{templatename}": {
AssertAction: rbac.ActionRead,
AssertObject: rbac.ResourceTemplate.InOrg(template.OrganizationID).WithID(template.ID.String()),
},

// These endpoints need payloads to get to the auth part. Payloads will be required
"PUT:/api/v2/users/{user}/roles": {StatusCode: http.StatusBadRequest, NoAuthorize: true},
Expand Down Expand Up @@ -292,6 +326,10 @@ func TestAuthorizeAllEndpoints(t *testing.T) {
route = strings.ReplaceAll(route, "{hash}", file.Hash)
route = strings.ReplaceAll(route, "{workspaceresource}", workspaceResources[0].ID.String())
route = strings.ReplaceAll(route, "{templateversion}", version.ID.String())
route = strings.ReplaceAll(route, "{templatename}", template.Name)
// Only checking org scoped params here
route = strings.ReplaceAll(route, "{scope}", string(organizationParam.Scope))
route = strings.ReplaceAll(route, "{id}", organizationParam.ScopeID.String())

resp, err := client.Request(context.Background(), method, route, nil)
require.NoError(t, err, "do req")
Expand Down
9 changes: 4 additions & 5 deletions coderd/database/databasefake/databasefake.go
Original file line number Diff line number Diff line change
Expand Up @@ -1283,11 +1283,10 @@ func (q *fakeQuerier) InsertProvisionerDaemon(_ context.Context, arg database.In
defer q.mutex.Unlock()

daemon := database.ProvisionerDaemon{
ID: arg.ID,
CreatedAt: arg.CreatedAt,
OrganizationID: arg.OrganizationID,
Name: arg.Name,
Provisioners: arg.Provisioners,
ID: arg.ID,
CreatedAt: arg.CreatedAt,
Name: arg.Name,
Provisioners: arg.Provisioners,
}
q.provisionerDaemons = append(q.provisionerDaemons, daemon)
return daemon, nil
Expand Down
1 change: 0 additions & 1 deletion coderd/database/dump.sql

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE provisioner_daemons ADD COLUMN organization_id uuid;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE provisioner_daemons DROP COLUMN organization_id;
4 changes: 4 additions & 0 deletions coderd/database/modelmethods.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ func (m OrganizationMember) RBACObject() rbac.Object {
func (o Organization) RBACObject() rbac.Object {
return rbac.ResourceOrganization.InOrg(o.ID).WithID(o.ID.String())
}

func (d ProvisionerDaemon) RBACObject() rbac.Object {
return rbac.ResourceProvisionerDaemon.WithID(d.ID.String())
}
11 changes: 5 additions & 6 deletions coderd/database/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 7 additions & 13 deletions coderd/database/queries.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions coderd/database/queries/provisionerdaemons.sql
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ INSERT INTO
provisioner_daemons (
id,
created_at,
organization_id,
"name",
provisioners
)
VALUES
($1, $2, $3, $4, $5) RETURNING *;
($1, $2, $3, $4) RETURNING *;

-- name: UpdateProvisionerDaemonByID :exec
UPDATE
Expand Down

0 comments on commit c04d045

Please sign in to comment.