feat: RBAC provisionerdaemons and parameters (#1755)

* chore: Remove org_id from provisionerdaemons
This commit is contained in:
Steven Masley
2022-05-26 11:20:54 -05:00
committed by GitHub
parent 104d07f659
commit c04d045279
18 changed files with 184 additions and 63 deletions

View File

@ -13,18 +13,27 @@ import (
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/parameter"
"github.com/coder/coder/coderd/rbac"
"github.com/coder/coder/codersdk"
)
func (api *API) postParameter(rw http.ResponseWriter, r *http.Request) {
var createRequest codersdk.CreateParameterRequest
if !httpapi.Read(rw, r, &createRequest) {
return
}
scope, scopeID, valid := readScopeAndID(rw, r)
if !valid {
return
}
obj, ok := api.parameterRBACResource(rw, r, scope, scopeID)
if !ok {
return
}
if !api.Authorize(rw, r, rbac.ActionUpdate, obj) {
return
}
var createRequest codersdk.CreateParameterRequest
if !httpapi.Read(rw, r, &createRequest) {
return
}
_, err := api.Database.GetParameterValueByScopeAndName(r.Context(), database.GetParameterValueByScopeAndNameParams{
Scope: scope,
ScopeID: scopeID,
@ -42,6 +51,7 @@ func (api *API) postParameter(rw http.ResponseWriter, r *http.Request) {
})
return
}
parameterValue, err := api.Database.InsertParameterValue(r.Context(), database.InsertParameterValueParams{
ID: uuid.New(),
Name: createRequest.Name,
@ -68,6 +78,15 @@ func (api *API) parameters(rw http.ResponseWriter, r *http.Request) {
if !valid {
return
}
obj, ok := api.parameterRBACResource(rw, r, scope, scopeID)
if !ok {
return
}
if !api.Authorize(rw, r, rbac.ActionRead, obj) {
return
}
parameterValues, err := api.Database.GetParameterValuesByScope(r.Context(), database.GetParameterValuesByScopeParams{
Scope: scope,
ScopeID: scopeID,
@ -94,6 +113,15 @@ func (api *API) deleteParameter(rw http.ResponseWriter, r *http.Request) {
if !valid {
return
}
obj, ok := api.parameterRBACResource(rw, r, scope, scopeID)
if !ok {
return
}
// A delete param is still updating the underlying resource for the scope.
if !api.Authorize(rw, r, rbac.ActionUpdate, obj) {
return
}
name := chi.URLParam(r, "name")
parameterValue, err := api.Database.GetParameterValueByScopeAndName(r.Context(), database.GetParameterValueByScopeAndNameParams{
Scope: scope,
@ -168,6 +196,53 @@ func convertParameterValue(parameterValue database.ParameterValue) codersdk.Para
}
}
// parameterRBACResource returns the RBAC resource a parameter scope and scope
// ID is trying to update. For RBAC purposes, adding a param to a resource
// is equivalent to updating/reading the associated resource.
// This means "parameters" are not a new resource, but an extension of existing
// ones.
func (api *API) parameterRBACResource(rw http.ResponseWriter, r *http.Request, scope database.ParameterScope, scopeID uuid.UUID) (rbac.Objecter, bool) {
ctx := r.Context()
var resource rbac.Objecter
var err error
switch scope {
case database.ParameterScopeWorkspace:
resource, err = api.Database.GetWorkspaceByID(ctx, scopeID)
case database.ParameterScopeTemplate:
resource, err = api.Database.GetTemplateByID(ctx, scopeID)
case database.ParameterScopeOrganization:
resource, err = api.Database.GetOrganizationByID(ctx, scopeID)
case database.ParameterScopeUser:
user, userErr := api.Database.GetUserByID(ctx, scopeID)
err = userErr
if err != nil {
// Use the userdata resource instead of the user. This way users
// can add user scoped params.
resource = rbac.ResourceUserData.WithID(user.ID.String()).WithOwner(user.ID.String())
}
case database.ParameterScopeImportJob:
// This scope does not make sense from this api.
// ImportJob params are created with the job, and the job id cannot
// be predicted.
err = xerrors.Errorf("ImportJob scope not supported")
default:
err = xerrors.Errorf("scope %q unsupported", scope)
}
// Write error payload to rw if we cannot find the resource for the scope
if err != nil {
if xerrors.Is(err, sql.ErrNoRows) {
httpapi.Forbidden(rw)
} else {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
Message: fmt.Sprintf("param scope resource: %s", err.Error()),
})
}
return nil, false
}
return resource, true
}
func readScopeAndID(rw http.ResponseWriter, r *http.Request) (database.ParameterScope, uuid.UUID, bool) {
var scope database.ParameterScope
switch chi.URLParam(r, "scope") {