| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1"> |
| <title>Apache Aurora</title> |
| <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"> |
| <link href="/assets/css/main.css" rel="stylesheet"> |
| <!-- Analytics --> |
| <script type="text/javascript"> |
| var _gaq = _gaq || []; |
| _gaq.push(['_setAccount', 'UA-45879646-1']); |
| _gaq.push(['_setDomainName', 'apache.org']); |
| _gaq.push(['_trackPageview']); |
| |
| (function() { |
| var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; |
| ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
| var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); |
| })(); |
| </script> |
| </head> |
| <body> |
| <div class="container-fluid section-header"> |
| <div class="container"> |
| <div class="nav nav-bar"> |
| <a href="/"><img src="/assets/img/aurora_logo_dkbkg.svg" width="300" alt="Transparent Apache Aurora logo with dark background"/></a> |
| <ul class="nav navbar-nav navbar-right"> |
| <li><a href="/documentation/latest/">Documentation</a></li> |
| <li><a href="/community/">Community</a></li> |
| <li><a href="/downloads/">Downloads</a></li> |
| <li><a href="/blog/">Blog</a></li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| |
| <div class="container-fluid"> |
| <div class="container content"> |
| <div class="col-md-12 documentation"> |
| <h5 class="page-header text-uppercase">Documentation |
| <select onChange="window.location.href='/documentation/' + this.value + '/design/command-hooks/'" |
| value="0.5.0-incubating"> |
| <option value="0.22.0" |
| > |
| 0.22.0 |
| (latest) |
| </option> |
| <option value="0.21.0" |
| > |
| 0.21.0 |
| </option> |
| <option value="0.20.0" |
| > |
| 0.20.0 |
| </option> |
| <option value="0.19.1" |
| > |
| 0.19.1 |
| </option> |
| <option value="0.19.0" |
| > |
| 0.19.0 |
| </option> |
| <option value="0.18.1" |
| > |
| 0.18.1 |
| </option> |
| <option value="0.18.0" |
| > |
| 0.18.0 |
| </option> |
| <option value="0.17.0" |
| > |
| 0.17.0 |
| </option> |
| <option value="0.16.0" |
| > |
| 0.16.0 |
| </option> |
| <option value="0.15.0" |
| > |
| 0.15.0 |
| </option> |
| <option value="0.14.0" |
| > |
| 0.14.0 |
| </option> |
| <option value="0.13.0" |
| > |
| 0.13.0 |
| </option> |
| <option value="0.12.0" |
| > |
| 0.12.0 |
| </option> |
| <option value="0.11.0" |
| > |
| 0.11.0 |
| </option> |
| <option value="0.10.0" |
| > |
| 0.10.0 |
| </option> |
| <option value="0.9.0" |
| > |
| 0.9.0 |
| </option> |
| <option value="0.8.0" |
| > |
| 0.8.0 |
| </option> |
| <option value="0.7.0-incubating" |
| > |
| 0.7.0-incubating |
| </option> |
| <option value="0.6.0-incubating" |
| > |
| 0.6.0-incubating |
| </option> |
| <option value="0.5.0-incubating" |
| selected="selected"> |
| 0.5.0-incubating |
| </option> |
| </select> |
| </h5> |
| <h1 id="command-hooks-for-the-aurora-client">Command Hooks for the Aurora Client</h1> |
| |
| <h2 id="introduction-motivation">Introduction/Motivation</h2> |
| |
| <p>We’ve got hooks in the client that surround API calls. These are |
| pretty awkward, because they don’t correlate with user actions. For |
| example, suppose we wanted a policy that said users weren’t allowed to |
| kill all instances of a production job at once.</p> |
| |
| <p>Right now, all that we could hook would be the “killJob” api call. But |
| kill (at least in newer versions of the client) normally runs in |
| batches. If a user called killall, what we would see on the API level |
| is a series of “killJob” calls, each of which specified a batch of |
| instances. We woudn’t be able to distinguish between really killing |
| all instances of a job (which is forbidden under this policy), and |
| carefully killing in batches (which is permitted.) In each case, the |
| hook would just see a series of API calls, and couldn’t find out what |
| the actual command being executed was!</p> |
| |
| <p>For most policy enforcement, what we really want to be able to do is |
| look at and vet the commands that a user is performing, not the API |
| calls that the client uses to implement those commands.</p> |
| |
| <p>So I propose that we add a new kind of hooks, which surround noun/verb |
| commands. A hook will register itself to handle a collection of (noun, |
| verb) pairs. Whenever any of those noun/verb commands are invoked, the |
| hooks methods will be called around the execution of the verb. A |
| pre-hook will have the ability to reject a command, preventing the |
| verb from being executed.</p> |
| |
| <h2 id="registering-hooks">Registering Hooks</h2> |
| |
| <p>These hooks will be registered two ways: |
| * Project hooks file. If a file named <code>AuroraHooks</code> is in the project directory |
| where an aurora command is being executed, that file will be read, |
| and its hooks will be registered. |
| * Configuration plugins. A configuration plugin can register hooks using an API. |
| Hooks registered this way are, effectively, hardwired into the client executable.</p> |
| |
| <p>The order of execution of hooks is unspecified: they may be called in |
| any order. There is no way to guarantee that one hook will execute |
| before some other hook.</p> |
| |
| <h3 id="global-hooks">Global Hooks</h3> |
| |
| <p>Commands registered by the python call are called <em>global</em> hooks, |
| because they will run for all configurations, whether or not they |
| specify any hooks in the configuration file.</p> |
| |
| <p>In the implementation, hooks are registered in the module |
| <code>apache.aurora.client.cli.command_hooks</code>, using the class <code>GlobalCommandHookRegistry</code>. A |
| global hook can be registered by calling <code>GlobalCommandHookRegistry.register_command_hook</code> |
| in a configuration plugin.</p> |
| |
| <h3 id="hook-files">Hook Files</h3> |
| |
| <p>A hook file is a file containing Python source code. It will be |
| dynamically loaded by the Aurora command line executable. After |
| loading, the client will check the module for a global variable named |
| “hooks”, which contains a list of hook objects, which will be added to |
| the hook registry.</p> |
| |
| <p>A project hooks file will be named <code>AuroraHooks</code>, |
| and will be located in either the directory where the command is being |
| executed, or one of its parent directories, up to the nearest git/mercurial |
| repository base.</p> |
| |
| <h3 id="the-api">The API</h3> |
| <pre class="highlight objective_c"><code><span style="background-color: #f8f8f8">class</span> <span style="background-color: #f8f8f8">CommandHook</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">object</span><span style="background-color: #f8f8f8">)</span> |
| <span style="color: #000000;font-weight: bold">@property</span> |
| <span style="background-color: #f8f8f8">def</span> <span style="background-color: #f8f8f8">name</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">self</span><span style="background-color: #f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span> |
| <span style="color: #d14">"""Returns a name for the hook."</span> |
| |
| <span style="background-color: #f8f8f8">def</span> <span style="background-color: #f8f8f8">get_nouns</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">self</span><span style="background-color: #f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span> |
| <span style="color: #d14">"""Return the nouns that have verbs that should invoke this hook."""</span> |
| |
| <span style="background-color: #f8f8f8">def</span> <span style="background-color: #f8f8f8">get_verbs</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">noun</span><span style="background-color: #f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span> |
| <span style="color: #d14">"""Return the verbs for a particular noun that should invoke his hook."""</span> |
| |
| <span style="color: #a61717;background-color: #e3d2d2">@abstractmethod</span> |
| <span style="background-color: #f8f8f8">def</span> <span style="background-color: #f8f8f8">pre_command</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">noun</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">verb</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">context</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">commandline</span><span style="background-color: #f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span> |
| <span style="color: #d14">"""Execute a hook before invoking a verb.</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> * noun: the noun being invoked.</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> * verb: the verb being invoked.</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> * context: the context object that will be used to invoke the verb.</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> The options object will be initialized before calling the hook</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> * commandline: the original argv collection used to invoke the client.</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> Returns: True if the command should be allowed to proceed; False if the command</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> should be rejected.</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> """</span> |
| |
| <span style="background-color: #f8f8f8">def</span> <span style="background-color: #f8f8f8">post_command</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">noun</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">verb</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">context</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">commandline</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">result</span><span style="background-color: #f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span> |
| <span style="color: #d14">"""Execute a hook after invoking a verb.</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> * noun: the noun being invoked.</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> * verb: the verb being invoked.</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> * context: the context object that will be used to invoke the verb.</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> The options object will be initialized before calling the hook</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> * commandline: the original argv collection used to invoke the client.</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> * result: the result code returned by the verb.</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> Returns: nothing</span><span style="color: #a61717;background-color: #e3d2d2"> |
| </span><span style="color: #d14"> """</span> |
| |
| <span style="background-color: #f8f8f8">class</span> <span style="background-color: #f8f8f8">GlobalCommandHookRegistry</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">object</span><span style="background-color: #f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span> |
| <span style="color: #a61717;background-color: #e3d2d2">@classmethod</span> |
| <span style="background-color: #f8f8f8">def</span> <span style="background-color: #f8f8f8">register_command_hook</span><span style="background-color: #f8f8f8">(</span><span style="background-color: #f8f8f8">self</span><span style="background-color: #f8f8f8">,</span> <span style="background-color: #f8f8f8">hook</span><span style="background-color: #f8f8f8">)</span><span style="color: #000000;font-weight: bold">:</span> |
| <span style="background-color: #f8f8f8">pass</span> |
| </code></pre> |
| |
| <h2 id="skipping-hooks">Skipping Hooks</h2> |
| |
| <p>In a perfect world, hooks would represent a global property or policy |
| that should always be enforced. Unfortunately, we don’t live in a |
| perfect world, which means that sometimes, every rule needs to get |
| broken.</p> |
| |
| <p>For example, an organization could decide that every configuration |
| must be checked in to source control before it could be |
| deployed. That’s an entirely reasonable policy. It would be easy to |
| implement it using a hook. But what if there’s a problem, and the |
| source repos is down?</p> |
| |
| <p>The easiest solution is just to allow a user to add a <code>--skip-hooks</code> |
| flag to the command-line. But doing that means that an organization |
| can’t actually use hooks to enforce policy, because users can skip |
| them whenever they want.</p> |
| |
| <p>Instead, we’d like to have a system where it’s possible to create |
| hooks to enforce policy, and then include a way of building policy |
| about when hooks can be skipped.</p> |
| |
| <p>I’m using sudo as a rough model for this. Many organizations need to |
| give people the ability to run privileged commands, but they still |
| want to have some control. Sudo allows them to specify who is allowed |
| to run a privileged command; where they’re allowed to run it; and what |
| command(s) they’re allowed to run. All of that is specified in a |
| special system file located in <code>/etc/sudoers</code> on a typical unix |
| machine.</p> |
| |
| <p>In a world of distributed systems, this approach has one grave |
| weakness. An aurora client can be located on any machine that has |
| network access to a Mesos/Aurora cluster. It can be run by a user in |
| pretty much any way they want - from a machine they control, from a |
| special chroot they created, etc. Relying an a file being in a special |
| location on their machine isn’t sufficient - it’s too easy to |
| maliciously or erroneously run a command in an environment with an |
| invalid hooks exceptions file.</p> |
| |
| <p>Instead, we’ve got two basic choices: hook exception rules can be |
| baked into the client executable, or they can be provided in a |
| network location.</p> |
| |
| <h3 id="specifying-when-hooks-can-be-skipped">Specifying when hooks can be skipped</h3> |
| |
| <h4 id="hooks-file">Hooks File</h4> |
| |
| <p>The module <code>apache.aurora.client.cli</code> contains a variable named |
| <code>GLOBAL_HOOK_SKIP_RULES_URL</code>. In the default distribution of Aurora, tihs variable contains |
| <code>None</code>. Users can modify this value for their local environments, providing |
| a site specific URL. If users attempt to bypass command hooks, and this |
| URL is not <code>None</code>, then the client will fetch the contents of that URL, and |
| attempt to interpret it as a hooks exception file.</p> |
| |
| <p>The hooks exception file is written in JSON, with the following structure:</p> |
| <pre class="highlight json"><code><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb"> </span><span style="color: #000080">"rulename"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> |
| </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb"> |
| </span><span style="color: #000080">"hooks"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">[</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"hook-name "</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">...</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">],</span><span style="color: #bbbbbb"> |
| </span><span style="color: #000080">"users"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">[</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">string</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">...</span><span style="background-color: #f8f8f8">],</span><span style="color: #bbbbbb"> |
| </span><span style="color: #000080">"commands"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb"> </span><span style="color: #000080">"job"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">[</span><span style="color: #d14">"kill"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"killall"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">...</span><span style="background-color: #f8f8f8">],</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">...</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">}</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> |
| </span><span style="color: #000080">"arg-patterns"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">[</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"regexp-str"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">...</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">]</span><span style="color: #bbbbbb"> |
| </span><span style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb"> |
| </span><span style="color: #a61717;background-color: #e3d2d2">...</span><span style="color: #bbbbbb"> |
| </span><span style="color: #a61717;background-color: #e3d2d2">}</span><span style="color: #bbbbbb"> |
| </span></code></pre> |
| |
| <ul> |
| <li><code>hooks</code> is a list of hook identifiers which can be skipped by a user |
| that satisfies this rule. If omitted, then this rule applies to <em>all hooks</em>. |
| (Omitting the <code>hooks</code> field is equivalent to giving it the value <code>['*']</code>.)</li> |
| <li><code>users</code> is a list of user names, or glob expressions that range over user |
| names. This rule gives permission to those users to skip hooks. If omitted, |
| then this rule allows <em>any user</em> to skip hooks that satisfy the rest of this rule. |
| Note that this is <em>user</em> names, not |
| <em>role</em> names: the rules specify users that are allowed to skip commands. |
| Some users that are allowed to work with a role account may be allowed to |
| skip, while others cannot.</li> |
| <li><code>commands</code> is a map from nouns to lists of verbs. If a command <code>aurora n v</code> |
| is being executed, this rule allows the hooks to be skipped if |
| <code>v</code> is in <code>commands[n]</code>. If this is omitted, then it allows hooks to be skipped for all |
| commands that satisfy the rest of the rule.</li> |
| <li><code>arg_patterns</code> is a list of glob patterns ranging over parameters. |
| If any of the parameters of the command match the parameters in this list, |
| the hook can be skipped. If ommitted, then this applies regardless of arguments.</li> |
| </ul> |
| |
| <p>For example, the following is a hook rules file which allows: |
| * The user “root” to skip any hook. |
| * Any user to skip hooks for test jobs. |
| * A specific group of users to skip hooks for jobs in cluster <code>east</code> |
| * Another group of users to skip hooks for <code>job kill</code> in cluster <code>west</code>.</p> |
| <pre class="highlight json"><code><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb"> |
| </span><span style="color: #000080">"allow-admin"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb"> </span><span style="color: #000080">"users"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">[</span><span style="color: #d14">"root"</span><span style="background-color: #f8f8f8">]</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb"> |
| </span><span style="color: #000080">"allow-test"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb"> </span><span style="color: #000080">"users"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">[</span><span style="color: #d14">"\*"</span><span style="background-color: #f8f8f8">],</span><span style="color: #bbbbbb"> </span><span style="color: #000080">"arg-patterns"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">[</span><span style="color: #d14">"\*/\*/test/\*"</span><span style="background-color: #f8f8f8">]</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb"> |
| </span><span style="color: #000080">"allow-east-users"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb"> </span><span style="color: #000080">"users"</span><span style="color: #a61717;background-color: #e3d2d2">=['john',</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">'mary',</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">'mike',</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">'sue'],</span><span style="color: #bbbbbb"> |
| </span><span style="color: #000080">"arg-patterns"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">[</span><span style="color: #d14">"east/\*/\*/\*"</span><span style="background-color: #f8f8f8">]</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">},</span><span style="color: #bbbbbb"> |
| </span><span style="color: #000080">"allow-west-kills"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb"> </span><span style="color: #000080">"users"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">[</span><span style="color: #d14">"anne"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"bill"</span><span style="background-color: #f8f8f8">,</span><span style="color: #bbbbbb"> </span><span style="color: #d14">"chris"</span><span style="background-color: #f8f8f8">],</span><span style="color: #bbbbbb"> |
| </span><span style="color: #000080">"commands"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">{</span><span style="color: #bbbbbb"> </span><span style="color: #000080">"job"</span><span style="background-color: #f8f8f8">:</span><span style="color: #bbbbbb"> </span><span style="background-color: #f8f8f8">[</span><span style="color: #d14">"kill"</span><span style="background-color: #f8f8f8">]},</span><span style="color: #bbbbbb"> </span><span style="color: #000080">"arg-patterns"</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">=</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">[</span><span style="color: #000080">"west/\*/\*/\*"</span><span style="color: #a61717;background-color: #e3d2d2">]</span><span style="color: #bbbbbb"> </span><span style="color: #a61717;background-color: #e3d2d2">}</span><span style="color: #bbbbbb"> |
| </span><span style="background-color: #f8f8f8">}</span><span style="color: #bbbbbb"> |
| </span></code></pre> |
| |
| <h4 id="programmatic-hooks-exceptions">Programmatic Hooks Exceptions</h4> |
| |
| <p>The <code>GlobalHooksRegistry</code> contains the method <code>add_hooks_exception</code>, which allows |
| users to register local hooks exceptions using the <code>ConfigurationPlugin</code> mechanism. |
| A hooks exception object implements the following interface:</p> |
| <pre class="highlight plaintext"><code>class HooksException(object): |
| def allow_exception(self, hooks, role, noun, verb, args): |
| """Params: |
| - hooks: a list of hook-names that the user wants to skip. If this |
| is ommitted, then this applies to all hooks. |
| - role: the role requesting that hooks be skipped. |
| - noun, verb: the noun and verb being executed. |
| - the other command-line arguments. |
| Returns: True if the user should be allowed to skip the requested hooks. |
| """ |
| return False |
| </code></pre> |
| |
| <p>When a user supplies the <code>--skip-hooks</code> argument, <code>allow_exception</code> is invoked on |
| each of the <code>HooksException</code> arguments. If <em>any</em> of the hooks exception objects |
| returns <code>True</code>, then the user will be permitted to skip the hooks.</p> |
| |
| <h3 id="skipping-hooks">Skipping Hooks</h3> |
| |
| <p>To skip a hook, a user uses a command-line option, <code>--skip-hooks</code>. The option can either |
| specify specific hooks to skip, or “all”:</p> |
| |
| <ul> |
| <li><code>aurora --skip-hooks=all job create east/bozo/devel/myjob</code> will create a job |
| without running any hooks.</li> |
| <li><code>aurora --skip-hooks=test,iq create east/bozo/devel/myjob</code> will create a job, |
| and will skip only the hooks named “test” and “iq”.</li> |
| </ul> |
| |
| <h2 id="changes">Changes</h2> |
| |
| <p>4/30: |
| * Rule exceptions are defined in JSON, and they are specified to be loaded from |
| a URL, not from a local file. |
| * Rule exceptions specify users, not roles.</p> |
| |
| <p>4/27: |
| Major changes between this and the last version of this proposal. |
| * Command hooks can’t be declared in a configuration file. There’s a simple |
| reason why: hooks run before a command’s implementation is invoked. |
| Config files are read during the commands invocation if necessary. If the |
| hook is declared in the config file, by the time you know that it should |
| have been run, it’s too late. So I’ve removed config-hooks from the |
| proposal. (API hooks defined by configs still work.) |
| * Skipping hooks. We expect aurora to be used inside of large |
| organizations. One of the primary use-cases of hooks is to create |
| enforcable policy that are specific to an organization. If hooks |
| can just be skipped because a user wants to skip them, it means that |
| the policy can’t be enforced, which defeats the purpose of having them. |
| So in this update, I propose a mechanism, loosely based on a <code>sudo</code>-like |
| mechanism for defining when hooks can be skipped.</p> |
| |
| </div> |
| |
| </div> |
| </div> |
| <div class="container-fluid section-footer buffer"> |
| <div class="container"> |
| <div class="row"> |
| <div class="col-md-2 col-md-offset-1"><h3>Quick Links</h3> |
| <ul> |
| <li><a href="/downloads/">Downloads</a></li> |
| <li><a href="/community/">Mailing Lists</a></li> |
| <li><a href="http://issues.apache.org/jira/browse/AURORA">Issue Tracking</a></li> |
| <li><a href="/documentation/latest/contributing/">How To Contribute</a></li> |
| </ul> |
| </div> |
| <div class="col-md-2"><h3>The ASF</h3> |
| <ul> |
| <li><a href="http://www.apache.org/licenses/">License</a></li> |
| <li><a href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li> |
| <li><a href="http://www.apache.org/foundation/thanks.html">Thanks</a></li> |
| <li><a href="http://www.apache.org/security/">Security</a></li> |
| </ul> |
| </div> |
| <div class="col-md-6"> |
| <p class="disclaimer">© 2014-2017 <a href="http://www.apache.org/">Apache Software Foundation</a>. Licensed under the <a href="http://www.apache.org/licenses/">Apache License v2.0</a>. The <a href="https://www.flickr.com/photos/trondk/12706051375/">Aurora Borealis IX photo</a> displayed on the homepage is available under a <a href="https://creativecommons.org/licenses/by-nc-nd/2.0/">Creative Commons BY-NC-ND 2.0 license</a>. Apache, Apache Aurora, and the Apache feather logo are trademarks of The Apache Software Foundation.</p> |
| </div> |
| </div> |
| </div> |
| |
| </body> |
| </html> |