-
Notifications
You must be signed in to change notification settings - Fork 35
Bug 1415868 - docs for actions with kind=hook #250
Conversation
This moves some of the more verbose schema descriptions out into the manual, leaving the schema quite a bit shorter. It will get longer when a new kind is added!
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.
Over all I LOVE this!!!
Most of my comments are suggestions, but refactoring the schema is probably a good idea.
src/manual/using/actions/schema.yml
Outdated
- task | ||
- type: object | ||
properties: | ||
kind: hook |
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 doesn't work
src/manual/using/actions/schema.yml
Outdated
items: | ||
type: object | ||
additionalProperties: | ||
allOf: |
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 propose refactoring the schema into:
oneOf:
- type: object
properties:
kind: {enum: task}
...
- type: object
properties:
kind: {enum: hook}
...
even the two kinds share some properties, just duplicate those properties. It's okay to document them twice.
The allOf
+ anyOf
refactoring is harder to do in your head.
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.
Another way to reference definitions with $ref
, this is okay if we render it using a viewer...
Putting definitions to be referenced under a top-level property definitions: {"mydef": ....}
is convention in json schemas. Then reference it with $ref: '#/definitions/mydef'
src/manual/using/actions/ui.md
Outdated
decision task couldn't do. | ||
|
||
Instead, the user interface should require the user to confirm each action, | ||
displaying the hookGroupId, hookId, and hookPayload. |
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.
Please add something like:
Furthermore, hook implementation should be designed to guard against malicious input,
which could be triggered by phishing an unsuspecting administrator to trigger a hook action
from a low privileged task with bad intend, causing an evilhookPayload
.
src/manual/using/actions/ui.md
Outdated
|
||
* it can limit the scopes available using | ||
[authorizedScopes](https://docs.taskcluster.net/manual/design/apis/hawk/authorized-scopes) | ||
based on some other definiitve information about the task -- for example, |
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.
*definiitve
src/manual/using/actions/spec.md
Outdated
|
||
The "task" kind requires that the user invoking the task has all of the scopes | ||
necessary to run the action task (and to create any further tasks). Such scopes | ||
might allow a user to perform undesirable actions with the Taskcluster API. |
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.
Granting such scopes allow a user to perform undesirable actions with the Taskcluster API
src/manual/using/actions/spec.md
Outdated
`hook-id:<hookGroupId>/<hookId>`. The method also verifies its payload against | ||
the hook's `triggerSchema`. This allows a controlled privilege escalation: | ||
only clients with the appropriate `trigger-hook` scope may trigger a hook, and | ||
only if they provide a payload matching the schema. If both of those conditions |
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.
only if they provide a payload matching the schema
^ this is not a security assertion, as the attacker controls the schema in actions.json
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.
Maybe rephrase this section... I love the sentence "This allows a controlled privilege escalation".
But I'm a little confused about the rest. As an action designer, using a hook means I can grant the user more restricted scopes. And I can use the hook to create a controlled privileged escalation, where my hook implementation sanitizes untrusted input.
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 meant matching triggerSchema, which the attacker does not control. What is the confusion?
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.
Okay, this is the triggerSchema
in hooks.. I didn't see that got added.
Curious, will that validate input from both HTTP triggers and pulse triggers...
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.
No, triggerSchema only applies to triggers. I think we decided to add an additional pulseMessageSchema, but I don't recall. Anyway, that part (pulse) isn't implemented yet.
src/manual/using/actions/spec.md
Outdated
JSON-e rendering performed by the hooks service. Do not confuse the two | ||
operations! | ||
|
||
### Choosing a Kind |
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.
Some of this belong more in action design guidelines than the action specification.
This is a nit, but it would be nice to corner these discussion topics and examples into a separate document.
But I'm okay with this here too :)
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 can move it to a guidelines.md
..
src/manual/using/actions/spec.md
Outdated
|
||
Once the hook is complete and functional, only then should you design the | ||
`actions.json` entry to trigger it. An "hook" action is just a template for how | ||
to call `hooks.triggerHook` and does not offer any level of security. |
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.
At this point you should remember that the schema is only for documentation, and you can rely on the integrity of
actions.json
for security.
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.
cannot?
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.
Yeah, cannot rely on...
src/manual/using/actions/spec.md
Outdated
are met, then the resulting task may execute with permissions the originating | ||
client does not posses. | ||
|
||
To design a hook-based action, start with the hook and consider the minimal |
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.
Could this be prefixed **Example, **
(in markdown)
That way it's easy to see that I don't care :)
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.
It's not an example, though..
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.
Could it have an informal title or something...
src/manual/using/actions/ui.md
Outdated
### "hook" Actions | ||
|
||
Hook actions have no such luxury, as they are intended to do things the | ||
decision task couldn't do. |
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.
We could add that UIs triggering hook actions should validate that the decision task posses the scope:
decision-task:reference-hook-action:<hookGroupId>/<hookId>
Obviously, the UI would have to call auth.expandScope(decisionTask.scopes)
to determine the scopes.
This would protect against the case where a try-decision task is tweaked to add an action that triggers the hook to release firefox. As scm_level_1
doesn't have permission to reference said action.
@djmitche, @imbstack, maybe think this over ^, I'll admit my initial thought is that this is too complicated. That this is something we'll get wrong every time we add a new hook action. On the hand scope errors like this should be easy to make visible and understand.
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.
Hm, I like that idea. It does sound like a good bit of work to implement, but not too bad..
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.
It is probably worth looking at what the releng scriptworkers are doing. @escapewindow might have some thoughts on this.
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.
It is probably worth looking at what the releng scriptworkers are doing. @escapewindow might have some thoughts on this.
That's a bit of a different situation -- recognizing a "legitimate" decision task for Firefox. The spec here is more general, and could apply to any project, Firefox or not, with any kind of decision task.
src/manual/using/actions/spec.md
Outdated
|
||
Variables | ||
--------- | ||
In practice it's encourage that consumers employ a facility that can generate |
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.
encouraged
src/manual/using/actions/schema.yml
Outdated
relevant. Thus, what context the action should be presented to the | ||
end-user. | ||
schema: | ||
$ref: http://json-schema.org/schema |
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.
Will this be a valid external reference for things that don't fetch external references?
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 don't know - I didn't change this part. This schema file is just to make Jonas happy anyway, and isn't machine-interpreted..
src/manual/using/actions/ui.md
Outdated
decision task couldn't do. | ||
|
||
Instead, the user interface should require the user to confirm each action, | ||
displaying the hookGroupId, hookId, and hookPayload. |
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.
Not that we necessarily need to do this now, but I wonder if we could make this even more solid. Very poorly thought out ideas:
- require linking to that hook in the tools site?
- suggest displaying a "you have run this hook N times before" the way browsers do with ssl/website stuff
- none of the above!
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.
Uh, maybe require the UI display the name
, description
and owner
properties of the hook.
That way a warning can be added to the description property indicating that the hook could do something bad... Stuff like that would smart..
I really like the decision-task-scopes thing, but I'm hesitant to introduce a new top-level scope name ( I can overcome my hesitation if necessary.. |
@djmitche, yeah, I don't like making a lot of new top-level scopes either... Maybe the top-level scope is related to actions.... The idea that there is a top-level scope that a task will need in-order to expose actions isn't crazy. But let's talk about how to mitigate phishing on vidyo or something. |
src/manual/using/actions/schema.yml
Outdated
- task | ||
- type: object | ||
properties: | ||
kind: {enum: hook} |
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 has to be kind: {enum: ['hook']}
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.
good point - I trusted #250 (comment) :)
src/manual/using/actions/schema.yml
Outdated
anyOf: | ||
- type: object | ||
properties: | ||
kind: {enum: task} |
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 should be {enum: ['task']}
We settled on scope Note that there's no reason to allow the user to work around this in the UI. If you want to test a hook, just call |
You might want to take this commit-by-commit.
Mostly I'd like some thought and feedback on the security implications. The risk is that someone makes a try job with the
retrigger
action configured to run hookproject-gecko/in-tree-action-3-relpromo
with a payload that promotes some malicious try build as Firefox 666. Then some innocent test task turns orange on the try job and they kindly ask someone in releng or relman to click "retrigger" for that task.My thinking is that a "generic" actions UI would run the user through two dialogs for an hook action:
The first can be skipped if there's no schema, of course.
Treeherder, however, can do a bit better:
authorizedScopes=['mozilla-group:scm_level_1']
for try, 2 for level-2 repos, etc.