Return-Path: X-Original-To: apmail-aurora-dev-archive@minotaur.apache.org Delivered-To: apmail-aurora-dev-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 064991095B for ; Wed, 26 Mar 2014 14:57:03 +0000 (UTC) Received: (qmail 89358 invoked by uid 500); 26 Mar 2014 14:57:02 -0000 Delivered-To: apmail-aurora-dev-archive@aurora.apache.org Received: (qmail 89209 invoked by uid 500); 26 Mar 2014 14:57:00 -0000 Mailing-List: contact dev-help@aurora.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@aurora.incubator.apache.org Delivered-To: mailing list dev@aurora.incubator.apache.org Received: (qmail 87946 invoked by uid 99); 26 Mar 2014 14:56:57 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 26 Mar 2014 14:56:57 +0000 X-ASF-Spam-Status: No, hits=-1998.3 required=5.0 tests=ALL_TRUSTED,HTML_MESSAGE,RP_MATCHES_RCVD X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO mail.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with SMTP; Wed, 26 Mar 2014 14:56:56 +0000 Received: (qmail 83487 invoked by uid 99); 26 Mar 2014 14:56:36 -0000 Received: from minotaur.apache.org (HELO minotaur.apache.org) (140.211.11.9) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 26 Mar 2014 14:56:35 +0000 Received: from localhost (HELO mail-pb0-f50.google.com) (127.0.0.1) (smtp-auth username mchucarroll, mechanism plain) by minotaur.apache.org (qpsmtpd/0.29) with ESMTP; Wed, 26 Mar 2014 14:56:35 +0000 Received: by mail-pb0-f50.google.com with SMTP id md12so2048853pbc.37 for ; Wed, 26 Mar 2014 07:56:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc:content-type; bh=ULBPT2n30n/GPoPNY6CRtm6NfjyrcHLpxR2gtLT0dIM=; b=HMOdDaddJFaju0mFvjpIp/pIqpompQR4p/q/yh6AB6bIpdgY8scGuhwO5W+6U6b0Ei C7nj3TBf6cAGDgdvouFX5E5zZPh3T9gmNXA28vMqinG4bZ5nf5yRVeevJxaWbiRBPfr5 v1Ln0e4mgkS03XV4tbW4RhKQ4RHF78kCbaT33lA76d5/CWMJ/ji2yfXIjpEnlFl3EGo+ ugLICWZlwx5ICDy28AYg0+lr1IgvT5Qklq93hoKnUT1+HfRoVb8oaT/saGnyGeAJq3pL MfeelvsYSimFHcFPBPabpzHdvQQ2NVv5IJnKzIRfErT7cVKhLcGACICmS5hYmvVnsvE4 QTUA== X-Gm-Message-State: ALoCoQnXktSJM3WvGT4WzVBzacb5AdJpoCNUMpRDjGTGMjqdoWveGHFE7ZaMJ1wxV1z/CqiWceoi MIME-Version: 1.0 X-Received: by 10.69.31.43 with SMTP id kj11mr85236706pbd.67.1395845795074; Wed, 26 Mar 2014 07:56:35 -0700 (PDT) Received: by 10.66.7.234 with HTTP; Wed, 26 Mar 2014 07:56:34 -0700 (PDT) In-Reply-To: References: Date: Wed, 26 Mar 2014 10:56:34 -0400 Message-ID: Subject: Re: Client Hooks proposal From: Mark Chu-Carroll To: Mark Chu-Carroll Cc: dev@aurora.incubator.apache.org Content-Type: multipart/alternative; boundary=001a113654fac6ea4904f583ace8 X-Virus-Checked: Checked by ClamAV on apache.org --001a113654fac6ea4904f583ace8 Content-Type: text/plain; charset=ISO-8859-1 This proposal contains one major error I realized last night. Pre-hooks run *before* verbs are invoked. That means that a pre-hook *can't* be declared in the config file: config files are read by the verb implementation, if the command takes one as a parameter. (It's possible to latch another phase of hook execution into the context, so that when a config gets loaded, it's checked for hooks, but I think that that is really ugly.) I'm currently implementing a version of command hooks that only includes hard-wired global hooks. Later, when I get to implementing a .aurora file with defaults, we can add hooks there, which will allow per-user/per-project hooks. -Mark On Tue, Mar 25, 2014 at 3:52 PM, Mark Chu-Carroll wrote: > Since I'm still stuck waiting on reviews, I figured I'd move on to one of > the next things on my agenda - Aurora-270, hooks for client commands. > Here's what Id like to implement - please beat me up with any criticisms > you have. > > 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. > > 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! > > 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. > > 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. > > These hooks will be registered two ways: > * By the global variable `COMMAND_HOOKS` in a configuration file; > * By a python method call. Hooks registered this way are, effectively, > hardwired into the client executable. > > Commands registered by the python call are called _global_ hooks, because > they > will run for all configurations, whether or not they specify any hooks in > the > configuration file. > > 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. > > Users can disable hooks by adding the option > `--disable-all-command-hooks`. The fact that they disabled the hooks will > be logged. > > > The API: > > class Hook(object) > def get_nouns(self): > """Return the nouns that have verbs that should invoke this > hook.""" > > def get_verbs(self, noun): > """Return the verbs for a particular noun that should invoke his > hook.""" > > @abstractmethod > def pre_command(self, noun, verb, context, commandline): > """Execute a hook before invoking a verb. > * noun: the noun being invoked. > * verb: the verb being invoked. > * context: the context object that will be used to invoke the verb. > The options object will be initialized before calling the hook > * commandline: the original argv collection used to invoke the > client. > Returns: True if the command should be allowed to proceed; False if the > command > should be rejected. > """ > > def post_command(self, noun, verb, context, commandline, result): > """Execute a hook after invoking a verb. > * noun: the noun being invoked. > * verb: the verb being invoked. > * context: the context object that will be used to invoke the verb. > The options object will be initialized before calling the hook > * commandline: the original argv collection used to invoke the > client. > * result: the result code returned by the verb. > Returns: nothing > """ > > --001a113654fac6ea4904f583ace8--