mirror of
https://github.com/coder/coder.git
synced 2025-07-06 15:41:45 +00:00
feat: RBAC provisionerdaemons and parameters (#1755)
* chore: Remove org_id from provisionerdaemons
This commit is contained in:
@ -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") {
|
||||
|
Reference in New Issue
Block a user