-
Notifications
You must be signed in to change notification settings - Fork 874
feat(coderd): add endpoint to list provisioner jobs #16029
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
664d9b7
to
77717c6
Compare
346ca29
to
ebaf498
Compare
77717c6
to
90a610a
Compare
ed828f6
to
8bee6f5
Compare
acee984
to
ad6da75
Compare
8bee6f5
to
d76be47
Compare
Would appreciate some rbac/dbauthz pointers here:
I'm actually not sure what we should enforce here. |
OrganizationID uuid.UUID `json:"organization_id" format:"uuid" table:"organization id"` | ||
Input ProvisionerJobInput `json:"input" table:"input,recursive_inline"` | ||
Type ProvisionerJobType `json:"type" table:"type"` | ||
AvailableWorkers []uuid.UUID `json:"available_workers,omitempty" format:"uuid" table:"available workers"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about future use cases, should we transform worker UUIDs into structures?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair. You might be able to add some stats about them. Like their tags? Idk
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The provisioner daemons endpoint (#16028) supports filtering by IDs, so you could request them from there. I don't think we should prematurely add data/structure until we know what/if it's needed.
coderd/database/modelmethods.go
Outdated
var input codersdk.ProvisionerJobInput | ||
_ = json.Unmarshal(p.Input, &input) // Best effort. | ||
|
||
// TODO(mafredri): Do we need to check provisioner permissions as well (p.AvailableProvisioners?). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only case I could imagine needing to check the permissions on the provisioner is if you are taking into account user-scoped provisioners {"scope": "user", "owner": "abc123..."}
.
The questions I'd raise here are:
- Do we want organization members to be able to view provisioners/jobs owned by other users?
- Do we want organization members to be able to view provisioners/jobs in other organizations?
For provisioner jobs, the answer for 1) should probably be no, as there may be inputs to provisioners that they're not meant to see.
For provisioner daemons, I don't think there's as much of a potential for information leakage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want organization members to be able to view provisioners/jobs owned by other users?
Provisioners are owned by an organization. All org members can read all provisioners today:
Lines 418 to 420 in 12991ff
// All users can see the provisioner daemons for workspace | |
// creation. | |
ResourceProvisionerDaemon.Type: {policy.ActionRead}, |
We have organizations to isolate provisioners if needed. No more granularity is currently supported.
Seeing other jobs should not be allowed. Checking permission of a list of jobs is a slow process.
Do we want organization members to be able to view provisioners/jobs in other organizations?
no we do not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized the premise for this RBACObject
is a bit broken. Essentially we would need access to template ID or workspace ID to check user-level permissions, but we only have template version ID and workspace build ID.
I don't think we want to introduce new RBAC resources for either of these so what would be a good way to solve it? Have a custom database.ProvisionerJobWithRBAC
or something where we have/join in the required IDs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mafredri it is a limitation that we currently have.
template_version
inherits the permissions from the template
. We do not have a resource for the version. The same is true for the workspace_build
. So you have to fetch the related resource to check the permissions.
To check a template_import
provisioner_job
, you need to fetch the template version, then the template, then check the perms.
This is done because if you add a new resource, there is no method today to add related permissions. Meaning, you cannot say "If you can read template A, then you can read version B and job C". So without the related permissions, we have to duplicate the perms consistently. Which can lead to bugs, so we just do the data relation fetched 🤷♂️
It is a limitation we have today, and I do not see it changing anytime soon.
or something where we have/join in the required IDs
We'd have to go this way. Maybe some new VIEW
. Right now we just pay the round trip costs of multiple fetches 😢. I'd support a new VIEW
that joins in the right resource IDs if we need it for listing purposes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not love leaving this open, but I get it.
As long as we don't break any existing APIs that might fetch a provisioner job today, I can be ok with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Emyrk fair. Most of the existing APIs don't apply any RBAC at all AFAICT, the just call directly out to DB in dbauthz.
The exception is GetProvisionerJobByID
fetches workspace/template based on job type, but this one wasn't updated to take into account the new rbac.ResourceProvisionerJobs
which would break existing functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of the existing APIs don't apply any RBAC at all AFAICT, the just call directly out to DB in dbauthz.
Yup, ideally all RBAC checks live in the dbauthz.
// owner := coderdtest.CreateFirstUser(t, client) | ||
// _, memberUser := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID) | ||
|
||
db, ps := dbtestutil.NewDB(t, dbtestutil.WithDumpOnFailure()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disgusting idea: use dbtestutil.NewDBWithSQLDB
and just insert the raw rows you want 😅
OrganizationID uuid.UUID `json:"organization_id" format:"uuid" table:"organization id"` | ||
Input ProvisionerJobInput `json:"input" table:"input,recursive_inline"` | ||
Type ProvisionerJobType `json:"type" table:"type"` | ||
AvailableWorkers []uuid.UUID `json:"available_workers,omitempty" format:"uuid" table:"available workers"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair. You might be able to add some stats about them. Like their tags? Idk
d76be47
to
0383f34
Compare
ad6da75
to
e4b4e2f
Compare
0383f34
to
be53b25
Compare
d967f4b
to
b1fbc82
Compare
9d3635f
to
0bf651b
Compare
a37b1bd
to
c924457
Compare
f7b1083
to
fb4c933
Compare
c924457
to
9525abd
Compare
fb4c933
to
aed586b
Compare
9525abd
to
51f628c
Compare
aed586b
to
2ad4bb4
Compare
51f628c
to
1b40a44
Compare
1b40a44
to
b6eb60d
Compare
b6eb60d
to
8d5fca2
Compare
d0477c6
to
dd49c08
Compare
dd49c08
to
0fd9aa7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it is in a mergeable state now. Good job!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! 👍
var detail string | ||
if e.Err != nil { | ||
detail = ": " + e.Err.Error() | ||
} | ||
return "unauthorized" + detail |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice 👍
// @Param status query codersdk.ProvisionerJobStatus false "Filter results by status" enums(pending,running,succeeded,canceling,canceled,failed) | ||
// @Success 200 {array} codersdk.ProvisionerJob | ||
// @Router /organizations/{organization}/provisionerjobs [get] | ||
func (api *API) provisionerJobs(rw http.ResponseWriter, r *http.Request) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, non-blocking: organizationProvisionerJobs
perhaps?
if !api.Authorize(r, policy.ActionRead, rbac.ResourceProvisionerJobs.InOrg(org.ID)) { | ||
httpapi.ResourceNotFound(rw) | ||
return | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 This is fine for the moment.
Stack:
feat(coderd): add endpoint to list provisioner jobs
Closes #15190
Updates #15084
Supercedes #15940