You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by vi...@apache.org on 2014/08/09 02:37:07 UTC

[1/2] git commit: Added authorization support for "/shutdown" endpoint and updated ACLs format.

Repository: mesos
Updated Branches:
  refs/heads/master 52cf9b3ff -> a5cc9b435


Added authorization support for "/shutdown" endpoint and updated
ACLs format.


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/a5cc9b43
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/a5cc9b43
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/a5cc9b43

Branch: refs/heads/master
Commit: a5cc9b435aad080a79230f0366a6ce77116c95a4
Parents: 94b9439
Author: Benjamin Hindman <be...@gmail.com>
Authored: Fri Aug 8 16:53:12 2014 -0700
Committer: Vinod Kone <vi...@gmail.com>
Committed: Fri Aug 8 17:03:17 2014 -0700

----------------------------------------------------------------------
 docs/authorization.md                    | 129 +++++++------
 include/mesos/mesos.proto                |  62 +++---
 src/authorizer/authorizer.cpp            |  93 +++------
 src/authorizer/authorizer.hpp            |  18 +-
 src/credentials/credentials.hpp          |   6 +-
 src/master/flags.hpp                     |  41 ++--
 src/master/http.cpp                      | 124 +++++++++---
 src/master/master.cpp                    |   4 +-
 src/master/master.hpp                    |  10 +
 src/sasl/authenticator.hpp               |   6 +-
 src/tests/authorization_tests.cpp        | 260 ++++----------------------
 src/tests/master_authorization_tests.cpp |  30 +--
 src/tests/mesos.cpp                      |   5 +-
 src/tests/mesos.hpp                      |  17 +-
 src/tests/reconciliation_tests.cpp       |   2 +-
 src/tests/script.cpp                     |   8 +-
 src/tests/shutdown_tests.cpp             | 109 ++++++++++-
 17 files changed, 425 insertions(+), 499 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/docs/authorization.md
----------------------------------------------------------------------
diff --git a/docs/authorization.md b/docs/authorization.md
index fea743a..6697944 100644
--- a/docs/authorization.md
+++ b/docs/authorization.md
@@ -6,11 +6,10 @@ layout: documentation
 
 Mesos 0.20.0 adds support for framework authorization. Authorization allows
 
- 1. Frameworks to only launch tasks/executors as authorized `users`.
- 2. Frameworks to be able to receive offers for authorized `roles`.
- 3. HTTP endpoints exposed by Mesos to be accessible to authorized `clients`.
+ 1. Frameworks to (re-)register with authorized `roles`.
+ 2. Frameworks to launch tasks/executors as authorized `users`.
+ 3. Authorized `principals` to shutdown framework(s) through "/shutdown" HTTP endpoint.
 
-> NOTE: While ACLs support for HTTP is present, currently access to the HTTP endpoints are not authorized.
 
 ## ACLs
 
@@ -20,40 +19,41 @@ Each ACL specifies a set of `Subjects` that can perform an `Action` on a set of
 
 The currently supported `Actions` are :
 
-1. "run_tasks" : Run tasks/executors
-2. "receive_offers" : Receive offers
-3. "http_get" : HTTP GET access
-4. "http_put" : HTTP_PUT access
+1. "register_frameworks" : Register Frameworks
+2. "run_tasks" : Run tasks/executors
+3. "shutdown_frameworks" : Shutdown frameworks
 
 The currently supported `Subjects` are :
 
-1. "principals" : Framework principals (used by "run_tasks" and "receive_offers" actions)
-2. "usernames" : Username used in HTTP Basic/Digest authentication. (used by "http_get" and "http_put" actions)
-3. "ips" : IP Addresses of the clients (used by "http_get" and "http_put" actions)
-4. "hostnames" : Hostnames of the clients (used by "http_get" and "http_put" actions)
+1. "principals"
+	- Framework principals (used by "register_frameworks" and "run_tasks" actions)
+	- Usernames (used by "shutdown_frameworks" action)
 
 The currently supported `Objects` are :
 
-1. "users" : Unix user to launch the task/executor as (used by "run_tasks" action)
-2. "roles" : Resource roles to receive offers from (used by "receive_offers" action)
-3. "urls" : HTTP URL endpoint exposed by the master (used by "http_get" and "http_put" actions)
+1. "roles" : Resource roles that framework can register with (used by "register_frameworks" action)
+2. "users" : Unix user to launch the task/executor as (used by "run_tasks" action)
+3. "framework_principals" : Framework principals that can be shutdown by HTTP POST (used by "shutdown_frameworks" action).
 
-> NOTE: Both `Subjects` and `Objects` can take a list of strings or special values (`ANY` and `NONE`).
+> NOTE: Both `Subjects` and `Objects` can take a list of strings or special values (`ANY` or `NONE`).
 
 
 ## How does it work?
 
-The Mesos master checks the ACLs to verify whether a request is authorized or not. For example, when  a framework launches a task, "run_tasks" ACLs are checked to see if the framework (`FrameworkInfo.principal`) is authorized to run the task/executor as the given user. If not authorized, the launch is rejected and the framework gets a TASK_LOST.
+The Mesos master checks the ACLs to verify whether a request is authorized or not.
 
-Similarly, when a framework (re-)registers the Mesos master checks whether it is authorized to receive offers for given resource role (`FrameworkInfo.role`). If not authorized, the framework is not allowed to (re-)register and gets an Error message back.
+For example, when a framework (re-)registers with the master, the "register_frameworks" ACLs are checked to see if the framework (`FrameworkInfo.principal`) is authorized to receive offers for the given resource role (`FrameworkInfo.role`). If not authorized, the framework is not allowed to (re-)register and gets an `Error` message back (which aborts the scheduler driver).
+
+Similarly, when a framework launches a task(s), "run_tasks" ACLs are checked to see if the framework (`FrameworkInfo.principal`) is authorized to run the task/executor as the given `user`. If not authorized, the launch is rejected and the framework gets a TASK_LOST.
+
+In the same vein, when a user/principal attempts to shutdown a framework through the "/shutdown" HTTP endpoint on the master, "shutdown_frameworks" ACLs are checked to see if the `principal` is authorized to shutdown the given framework. If not authorized, the shutdown is rejected and the user receives an `Unauthorized` HTTP response.
 
-While not yet implemented, GET/PUT access to HTTP endpoints exposed by the Mesos master will be authorized in a similar way.
 
 There are couple of important things to note:
 
 1. ACLs are matched in the order that they are setup. In other words, the first matching ACL determines whether a request is authorized or not.
 
-2. If none of the specified ACLs match the given request, whether the request is authorized or not is defined by `ACLs.permissive` field. By default this "true" i.e., a non-matching request is authorized.
+2. If none of the specified ACLs match the given request, whether the request is authorized or not is defined by `ACLs.permissive` field. By default this is "true" i.e., a non-matching request is authorized.
 
 
 ## Examples
@@ -66,7 +66,7 @@ There are couple of important things to note:
                                "principals": { "values": ["foo", "bar"] },
                                "users": { "values": ["alice"] }
                              }
-                           ],
+                           ]
             }
 
 2. Any framework can run tasks as user `guest`.
@@ -77,7 +77,7 @@ There are couple of important things to note:
                                "principals": { "type": "ANY" },
                                "users": { "values": ["guest"] }
                              }
-                           ],
+                           ]
             }
 
 3. No framework can run tasks as `root`.
@@ -88,7 +88,7 @@ There are couple of important things to note:
                                "principals": { "type": "NONE" },
                                "users": { "values": ["root"] }
                              }
-                           ],
+                           ]
             }
 
 
@@ -102,52 +102,66 @@ There are couple of important things to note:
                              },
                              {
                                "principals": { "values": [ "foo" ] },
-                               "users": { "type": ["NONE"] }
+                               "users": { "type": "NONE" }
                              }
-                           ],
+                           ]
             }
 
 
 
 
-5. Framework `foo` can be offered resources for `analytics` and `ads` roles.
+5. Framework `foo` can register with `analytics` and `ads` roles.
 
             {
-              "receive_offers": [
-                                  {
-                                    "principals": { "values": ["foo"] },
-                                    "roles": { "values": ["analytics", "ads"] }
-                                  }
-                                ],
+              "register_frameworks": [
+                                       {
+                                         "principals": { "values": ["foo"] },
+                                         "roles": { "values": ["analytics", "ads"] }
+                                       }
+                                     ]
             }
 
 
-6. Only framework `foo` and no one else can be offered resources for `analytics` role.
+6. Only framework `foo` and no one else can register with `analytics` role.
 
             {
-              "receive_offers": [
-                                  {
-                                    "principals": { "values": ["foo"] },
-                                    "roles": { "values": ["analytics"] }
-                                  },
-                                  {
-                                    "principals": { "type": "NONE" },
-                                    "roles": { "values": ["analytics"] }
-                                  }
-                                ],
+              "register_frameworks": [
+                                       {
+                                         "principals": { "values": ["foo"] },
+                                         "roles": { "values": ["analytics"] }
+                                       },
+                                       {
+                                         "principals": { "type": "NONE" },
+                                         "roles": { "values": ["analytics"] }
+                                       }
+                                     ]
             }
 
-7. Framework `foo` can only receive offers for `analytics` role but no other roles. Also, no other framework can receive offers for any role.
+7. Framework `foo` can only register with `analytics` role but no other roles. Also, no other framework can register with any roles.
 
             {
               "permissive" : "false",
 
-              "receive_offers": [
-                                  {
-                                    "principals": { "values": ["foo"] },
-                                    "roles": { "values": ["analytics"] }
-                                  }
-                                ],
+              "register_frameworks": [
+                                       {
+                                         "principals": { "values": ["foo"] },
+                                         "roles": { "values": ["analytics"] }
+                                       }
+                                     ]
+            }
+
+
+8. Only `ops` principal can shutdown any frameworks through "/shutdown" HTTP endpoint.
+
+            {
+              "permissive" : "false",
+
+              "shutdown_frameworks": [
+                                       {
+                                         "principals": { "values": ["ops"] },
+                                         "framework_principals": { "type": "ANY" }
+                                       }
+                                     ]
             }
 
 
@@ -161,20 +175,5 @@ As part of this feature, a new flag was added to the master.
             or '/path/to/file'.
             See the ACLs protobuf in mesos.proto for the expected format.
 
-            Example:
-            {
-              "run_tasks": [
-                             {
-                               "principals": { "values": ["a", "b"] },
-                               "users": { "values": ["root"] }
-                             }
-                           ],
-              "receive_offers": [
-                                  {
-                                    "principals": { "type": "ANY" },
-                                    "roles": { "values": ["foo"] }
-                                  }
-                                ]
-            }
 
 **For the complete list of master options: ./mesos-master.sh --help**

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/include/mesos/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/mesos.proto b/include/mesos/mesos.proto
index efb4239..cc9f20e 100644
--- a/include/mesos/mesos.proto
+++ b/include/mesos/mesos.proto
@@ -658,12 +658,13 @@ message Parameters {
 
 
 /**
- * Credential used for authentication.
+ * Credential used in various places for authentication and
+ * authorization.
  *
- * NOTE: The 'principal' is used for authenticating the framework or slave
- * with the master. This is different from 'FrameworkInfo.user'
- * which is used to determine the user under which the framework's
- * executors/tasks are run.
+ * NOTE: A 'principal' is different from 'FrameworkInfo.user'. The
+ * former is used for authentication and authorization while the
+ * latter is used to determine the default user under which the
+ * framework's executors/tasks are run.
  */
 message Credential {
   required string principal = 1;
@@ -672,18 +673,12 @@ message Credential {
 
 
 /**
- * Credentials used for authentication.
- *
+ * Credentials used for framework authentication, HTTP authentication
+ * (where the common 'username' and 'password' are captured as
+ * 'principal' and 'secret' respectively), etc.
  */
 message Credentials {
-  // Collection of credentials used to authenticate "registration" of
-  // either frameworks or slaves.
-  repeated Credential registration = 1;
-
-  // Collection of credentails used to authenticate HTTP endpoints
-  // (where the common "username" and "password" are captured as
-  // 'principal' and 'secret' respectively).
-  repeated Credential http = 2;
+  repeated Credential credentials = 1;
 }
 
 
@@ -707,40 +702,30 @@ message ACL {
   }
 
   // ACLs.
-  message RunTasks {
+  message RegisterFramework {
     // Subjects.
     required Entity principals = 1; // Framework principals.
 
     // Objects.
-    required Entity users = 2; // Users to run the tasks/executors as.
+    required Entity roles = 2; // Roles for resource offers.
   }
 
-  message ReceiveOffers {
+  message RunTask {
     // Subjects.
     required Entity principals = 1; // Framework principals.
 
     // Objects.
-    required Entity roles = 2; // Resource roles that can be offered.
-  }
-
-  message HTTPGet {
-    // Subjects (At least one of these should be set).
-    optional Entity usernames = 1; // HTTP authentication based usernames.
-    optional Entity ips = 2;
-    optional Entity hostnames = 3;
-
-    // Objects.
-    required Entity urls = 4;
+    required Entity users = 2; // Users to run the tasks/executors as.
   }
 
-  message HTTPPut {
-    // Subjects (At least one of these should be set).
-    optional Entity usernames = 1; // HTTP authentication based usernames.
-    optional Entity ips = 2;
-    optional Entity hostnames = 3;
+  // Which principals are authorized to shutdown frameworks of other
+  // principals.
+  message ShutdownFramework {
+    // Subjects.
+    required Entity principals = 1;
 
     // Objects.
-    required Entity urls = 4;
+    required Entity framework_principals = 2;
   }
 }
 
@@ -766,10 +751,9 @@ message ACL {
  */
 message ACLs {
   optional bool permissive = 1 [default = true];
-  repeated ACL.RunTasks run_tasks = 2;
-  repeated ACL.ReceiveOffers receive_offers = 3;
-  repeated ACL.HTTPGet http_get = 4;
-  repeated ACL.HTTPPut http_put = 5;
+  repeated ACL.RegisterFramework register_frameworks = 2;
+  repeated ACL.RunTask run_tasks = 3;
+  repeated ACL.ShutdownFramework shutdown_frameworks = 4;
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/authorizer/authorizer.cpp
----------------------------------------------------------------------
diff --git a/src/authorizer/authorizer.cpp b/src/authorizer/authorizer.cpp
index 40a14be..21e97e3 100644
--- a/src/authorizer/authorizer.cpp
+++ b/src/authorizer/authorizer.cpp
@@ -54,73 +54,53 @@ public:
   LocalAuthorizerProcess(const ACLs& _acls)
     : ProcessBase(process::ID::generate("authorizer")), acls(_acls) {}
 
-  Future<bool> authorize(const ACL::RunTasks& request)
+  Future<bool> authorize(const ACL::RegisterFramework& request)
   {
-    foreach (const ACL::RunTasks& acl, acls.run_tasks()) {
+    foreach (const ACL::RegisterFramework& acl, acls.register_frameworks()) {
       // ACL matches if both subjects and objects match.
       if (matches(request.principals(), acl.principals()) &&
-          matches(request.users(), acl.users())) {
+          matches(request.roles(), acl.roles())) {
         // ACL is allowed if both subjects and objects are allowed.
         return allows(request.principals(), acl.principals()) &&
-               allows(request.users(), acl.users());
+               allows(request.roles(), acl.roles());
       }
     }
 
     return acls.permissive(); // None of the ACLs match.
   }
 
-  Future<bool> authorize(const ACL::ReceiveOffers& request)
+  Future<bool> authorize(const ACL::RunTask& request)
   {
-    foreach (const ACL::ReceiveOffers& acl, acls.receive_offers()) {
+    foreach (const ACL::RunTask& acl, acls.run_tasks()) {
       // ACL matches if both subjects and objects match.
       if (matches(request.principals(), acl.principals()) &&
-          matches(request.roles(), acl.roles())) {
+          matches(request.users(), acl.users())) {
         // ACL is allowed if both subjects and objects are allowed.
         return allows(request.principals(), acl.principals()) &&
-               allows(request.roles(), acl.roles());
+               allows(request.users(), acl.users());
       }
     }
 
     return acls.permissive(); // None of the ACLs match.
   }
 
-  Future<bool> authorize(const ACL::HTTPGet& request)
+  Future<bool> authorize(const ACL::ShutdownFramework& request)
   {
-    foreach (const ACL::HTTPGet& acl, acls.http_get()) {
+    foreach (const ACL::ShutdownFramework& acl, acls.shutdown_frameworks()) {
       // ACL matches if both subjects and objects match.
-      if (matches(request.usernames(), acl.usernames()) &&
-          matches(request.ips(), acl.ips()) &&
-          matches(request.hostnames(), acl.hostnames()) &&
-          matches(request.urls(), acl.urls())) {
+      if (matches(request.principals(), acl.principals()) &&
+          matches(request.framework_principals(),
+                  acl.framework_principals())) {
         // ACL is allowed if both subjects and objects are allowed.
-        return allows(request.usernames(), acl.usernames()) &&
-               allows(request.ips(), acl.ips()) &&
-               allows(request.hostnames(), acl.hostnames()) &&
-               allows(request.urls(), acl.urls());
+        return allows(request.principals(), acl.principals()) &&
+               allows(request.framework_principals(),
+                      acl.framework_principals());
       }
     }
 
     return acls.permissive(); // None of the ACLs match.
   }
 
-  Future<bool> authorize(const ACL::HTTPPut& request)
-  {
-    foreach (const ACL::HTTPPut& acl, acls.http_put()) {
-      // ACL matches if both subjects and objects match.
-      if (matches(request.usernames(), acl.usernames()) &&
-          matches(request.ips(), acl.ips()) &&
-          matches(request.hostnames(), acl.hostnames()) &&
-          matches(request.urls(), acl.urls())) {
-        // ACL is allowed if both subjects and objects are allowed.
-        return allows(request.usernames(), acl.usernames()) &&
-               allows(request.ips(), acl.ips()) &&
-               allows(request.hostnames(), acl.hostnames()) &&
-               allows(request.urls(), acl.urls());
-      }
-    }
-
-    return acls.permissive(); // None of the ACLs match.
-  }
 private:
   // Match matrix:
   //
@@ -263,61 +243,36 @@ LocalAuthorizer::~LocalAuthorizer()
 
 Try<Owned<LocalAuthorizer> > LocalAuthorizer::create(const ACLs& acls)
 {
-  // Validate ACLs.
-  foreach (const ACL::HTTPGet& acl, acls.http_get()) {
-    // At least one of the subjects should be set.
-    if (acl.has_usernames() + acl.has_ips() + acl.has_hostnames() < 1) {
-      return Error("At least one of the subjects should be set for ACL: " +
-                    acl.DebugString());
-    }
-  }
-
-  foreach (const ACL::HTTPPut& acl, acls.http_put()) {
-    // At least one of the subjects should be set.
-    if (acl.has_usernames() + acl.has_ips() + acl.has_hostnames() < 1) {
-       return Error("At least one of the subjects should be set for ACL: " +
-                     acl.DebugString());
-     }
-  }
-
   return new LocalAuthorizer(acls);
 }
 
 
-Future<bool> LocalAuthorizer::authorize(const ACL::RunTasks& request)
-{
-  // Necessary to disambiguate.
-  typedef Future<bool>(LocalAuthorizerProcess::*F)(const ACL::RunTasks&);
-
-  return dispatch(
-      process, static_cast<F>(&LocalAuthorizerProcess::authorize), request);
-}
-
-
-Future<bool> LocalAuthorizer::authorize(const ACL::ReceiveOffers& request)
+Future<bool> LocalAuthorizer::authorize(const ACL::RegisterFramework& request)
 {
   // Necessary to disambiguate.
-  typedef Future<bool>(LocalAuthorizerProcess::*F)(const ACL::ReceiveOffers&);
+  typedef Future<bool>(LocalAuthorizerProcess::*F)(
+      const ACL::RegisterFramework&);
 
   return dispatch(
       process, static_cast<F>(&LocalAuthorizerProcess::authorize), request);
 }
 
 
-Future<bool> LocalAuthorizer::authorize(const ACL::HTTPGet& request)
+Future<bool> LocalAuthorizer::authorize(const ACL::RunTask& request)
 {
   // Necessary to disambiguate.
-  typedef Future<bool>(LocalAuthorizerProcess::*F)(const ACL::HTTPGet&);
+  typedef Future<bool>(LocalAuthorizerProcess::*F)(const ACL::RunTask&);
 
   return dispatch(
       process, static_cast<F>(&LocalAuthorizerProcess::authorize), request);
 }
 
 
-Future<bool> LocalAuthorizer::authorize(const ACL::HTTPPut& request)
+Future<bool> LocalAuthorizer::authorize(const ACL::ShutdownFramework& request)
 {
   // Necessary to disambiguate.
-  typedef Future<bool>(LocalAuthorizerProcess::*F)(const ACL::HTTPPut&);
+  typedef Future<bool>(LocalAuthorizerProcess::*F)(
+      const ACL::ShutdownFramework&);
 
   return dispatch(
       process, static_cast<F>(&LocalAuthorizerProcess::authorize), request);

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/authorizer/authorizer.hpp
----------------------------------------------------------------------
diff --git a/src/authorizer/authorizer.hpp b/src/authorizer/authorizer.hpp
index b7f1119..c039d94 100644
--- a/src/authorizer/authorizer.hpp
+++ b/src/authorizer/authorizer.hpp
@@ -49,13 +49,11 @@ public:
   // A failed future indicates a transient failure and the user
   // can (should) retry.
   virtual process::Future<bool> authorize(
-      const ACL::RunTasks& request) = 0;
+      const ACL::RegisterFramework& request) = 0;
   virtual process::Future<bool> authorize(
-      const ACL::ReceiveOffers& request) = 0;
+      const ACL::RunTask& request) = 0;
   virtual process::Future<bool> authorize(
-      const ACL::HTTPGet& request) = 0;
-  virtual process::Future<bool> authorize(
-      const ACL::HTTPPut& request) = 0;
+      const ACL::ShutdownFramework& request) = 0;
 
 protected:
   Authorizer() {}
@@ -71,10 +69,12 @@ public:
   virtual ~LocalAuthorizer();
 
   // Implementation of Authorizer interface.
-  virtual process::Future<bool> authorize(const ACL::RunTasks& request);
-  virtual process::Future<bool> authorize(const ACL::ReceiveOffers& request);
-  virtual process::Future<bool> authorize(const ACL::HTTPGet& request);
-  virtual process::Future<bool> authorize(const ACL::HTTPPut& request);
+  virtual process::Future<bool> authorize(
+      const ACL::RegisterFramework& request);
+  virtual process::Future<bool> authorize(
+      const ACL::RunTask& request);
+  virtual process::Future<bool> authorize(
+      const ACL::ShutdownFramework& request);
 
 private:
   LocalAuthorizer(const ACLs& acls);

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/credentials/credentials.hpp
----------------------------------------------------------------------
diff --git a/src/credentials/credentials.hpp b/src/credentials/credentials.hpp
index 1790793..4cdadb1 100644
--- a/src/credentials/credentials.hpp
+++ b/src/credentials/credentials.hpp
@@ -53,7 +53,7 @@ inline Result<Credentials> read(const std::string& path)
                  << "credentials file is NOT accessible by others.";
   }
 
-  // TODO(ijimenez) deprecate text support only JSON like acls
+  // TODO(ijimenez): Deprecate text and support only JSON like ACLs.
   Try<JSON::Object> json = JSON::parse<JSON::Object>(read.get());
   if (!json.isError()) {
     Try<Credentials> credentials = ::protobuf::parse<Credentials>(json.get());
@@ -67,11 +67,11 @@ inline Result<Credentials> read(const std::string& path)
     const std::vector<std::string>& pairs = strings::tokenize(line, " ");
     if (pairs.size() != 2) {
         return Error("Invalid credential format at line " +
-                     stringify(credentials.registration().size() + 1));
+                     stringify(credentials.credentials().size() + 1));
     }
 
     // Add the credential.
-    Credential* credential = credentials.add_registration();
+    Credential* credential = credentials.add_credentials();
     credential->set_principal(pairs[0]);
     credential->set_secret(pairs[1]);
   }

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/master/flags.hpp
----------------------------------------------------------------------
diff --git a/src/master/flags.hpp b/src/master/flags.hpp
index 0db4c95..5e9ecb5 100644
--- a/src/master/flags.hpp
+++ b/src/master/flags.hpp
@@ -213,24 +213,17 @@ public:
         "Either a path to a text file with a list of credentials,\n"
         "each line containing 'principal' and 'secret' separated by "
         "whitespace,\n"
-        "or, a path to a JSON-formatted file containing credentials\n"
-        "for identification/registration and http authentication."
+        "or, a path to a JSON-formatted file containing credentials.\n"
         "Path could be of the form 'file:///path/to/file' or '/path/to/file'."
         "\n"
         "JSON file Example:\n"
         "{\n"
-        "  \"http\": [\n"
-        "             {\n"
-        "                \"principal\": \"username\",\n"
-        "                \"secret\": \"secret\",\n"
-        "             }\n"
-        "            ],\n"
-        "  \"identification\": [\n"
-        "                       {\n"
-        "                          \"principal\": \"username\",\n"
-        "                          \"secret\": \"secret\",\n"
-        "                       }\n"
-        "                      ]\n"
+        "  \"credentials\": [\n"
+        "                    {\n"
+        "                       \"principal\": \"sherman\",\n"
+        "                       \"secret\": \"kitesurf\",\n"
+        "                    }\n"
+        "                   ]\n"
         "}\n"
         "Text file Example:\n"
         "username secret\n"
@@ -247,18 +240,24 @@ public:
         "\n"
         "Example:\n"
         "{\n"
+        "  \"register_frameworks\": [\n"
+        "                       {\n"
+        "                          \"principals\": { \"type\": \"ANY\" },\n"
+        "                          \"roles\": { \"values\": [\"a\"] }\n"
+        "                       }\n"
+        "                     ],\n"
         "  \"run_tasks\": [\n"
         "                  {\n"
         "                     \"principals\": { \"values\": [\"a\", \"b\"] },\n"
-        "                     \"users\": { \"values\": [\"root\"] }\n"
+        "                     \"users\": { \"values\": [\"c\"] }\n"
         "                  }\n"
         "                ],\n"
-        "  \"receive_offers\": [\n"
-        "                       {\n"
-        "                          \"principals\": { \"type\": \"ANY\" },\n"
-        "                          \"roles\": { \"values\": [\"foo\"] }\n"
-        "                       }\n"
-        "                     ]\n"
+        "  \"shutdown_frameworks\": [\n"
+        "                {\n"
+        "                   \"principals\": { \"values\": [\"a\", \"b\"] },\n"
+        "                   \"framework_principals\": { \"values\": [\"c\"] }\n"
+        "                }\n"
+        "              ]\n"
         "}");
 
     add(&Flags::rate_limits,

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/master/http.cpp
----------------------------------------------------------------------
diff --git a/src/master/http.cpp b/src/master/http.cpp
index f2ca659..9317a95 100644
--- a/src/master/http.cpp
+++ b/src/master/http.cpp
@@ -39,6 +39,8 @@
 #include <stout/result.hpp>
 #include <stout/strings.hpp>
 
+#include "authorizer/authorizer.hpp"
+
 #include "common/attributes.hpp"
 #include "common/build.hpp"
 #include "common/http.hpp"
@@ -620,42 +622,80 @@ const string Master::Http::SHUTDOWN_HELP = HELP(
 
 Future<Response> Master::Http::shutdown(const Request& request)
 {
-  if (master->credentials.isNone()) {
-    return Unauthorized("Mesos master");
+  if (request.method != "POST") {
+    return BadRequest("Expecting POST");
   }
+
+  // Parse the query string in the request body (since this is a POST)
+  // in order to determine the framework ID to shutdown.
   hashmap<string, string> values =
     process::http::query::parse(request.body);
-  Option<string> frameworkId = values.get("frameworkId");
-  if (frameworkId.isNone()) {
-    return BadRequest();
+
+  if (values.get("frameworkId").isNone()) {
+    return BadRequest("Missing 'frameworkId' query parameter");
   }
+
   FrameworkID id;
-  id.set_value(frameworkId.get());
+  id.set_value(values.get("frameworkId").get());
+
   Framework* framework = master->getFramework(id);
 
-  Option<string> authHeader = request.headers.get("Authorization");
-  if (authHeader.isNone()) {
-    return Unauthorized("Mesos master");
+  if (framework == NULL) {
+    return BadRequest("No framework found with specified ID");
   }
-  const string& decodedAuth =
-    base64::decode(strings::split(authHeader.get(), " ", 2)[1]);
-  const std::vector<string>& pairs = strings::split(decodedAuth, ":", 2);
-  if (pairs.size() != 2) {
+
+  Result<Credential> credential = authenticate(request);
+
+  if (credential.isError()) {
+    return Unauthorized("Mesos master", credential.error());
+  }
+
+  // Skip authorization if no ACLs were provided to the master.
+  if (master->authorizer.isNone()) {
+    return _shutdown(id);
+  }
+
+  mesos::ACL::ShutdownFramework shutdown;
+
+  if (credential.isSome()) {
+    shutdown.mutable_principals()->add_values(credential.get().principal());
+  } else {
+    shutdown.mutable_principals()->set_type(ACL::Entity::ANY);
+  }
+
+  if (framework->info.has_principal()) {
+    shutdown.mutable_framework_principals()->add_values(
+        framework->info.principal());
+  } else {
+    shutdown.mutable_framework_principals()->set_type(ACL::Entity::ANY);
+  }
+
+  lambda::function<Future<Response>(bool)> _shutdown =
+    lambda::bind(&Master::Http::_shutdown, this, id, lambda::_1);
+
+  return master->authorizer.get()->authorize(shutdown)
+    .then(defer(master->self(), _shutdown));
+}
+
+
+Future<Response> Master::Http::_shutdown(
+    const FrameworkID& id,
+    bool authorized)
+{
+  if (!authorized) {
     return Unauthorized("Mesos master");
   }
 
-  const string& username = pairs[0];
-  const string& password = pairs[1];
+  Framework* framework = master->getFramework(id);
 
-  foreach (const Credential& credential, master->credentials.get().http()) {
-    if (credential.principal() == username &&
-        (!credential.has_secret() || credential.secret() == password)) {
-      // TODO(ijimenez) make removeFramework asynchronously
-      master->removeFramework(framework);
-      return OK();
-    }
+  if (framework == NULL) {
+    return BadRequest("No framework found with ID " + stringify(id));
   }
-  return Unauthorized("Mesos master");
+
+  // TODO(ijimenez): Do 'removeFramework' asynchronously.
+  master->removeFramework(framework);
+
+  return OK();
 }
 
 
@@ -780,6 +820,44 @@ Future<Response> Master::Http::tasks(const Request& request)
 }
 
 
+Result<Credential> Master::Http::authenticate(const Request& request)
+{
+  // By default, assume everyone is authenticated if no credentials
+  // were provided.
+  if (master->credentials.isNone()) {
+    return None();
+  }
+
+  Option<string> authorization = request.headers.get("Authorization");
+
+  if (authorization.isNone()) {
+    return Error("Missing 'Authorization' request header");
+  }
+
+  const string& decoded =
+    base64::decode(strings::split(authorization.get(), " ", 2)[1]);
+
+  const vector<string>& pairs = strings::split(decoded, ":", 2);
+
+  if (pairs.size() != 2) {
+    return Error("Malformed 'Authorization' request header");
+  }
+
+  const string& username = pairs[0];
+  const string& password = pairs[1];
+
+  foreach (const Credential& credential,
+          master->credentials.get().credentials()) {
+    if (credential.principal() == username &&
+        credential.secret() == password) {
+      return credential;
+    }
+  }
+
+  return Error("Could not authenticate '" + username + "'");
+}
+
+
 } // namespace master {
 } // namespace internal {
 } // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/master/master.cpp
----------------------------------------------------------------------
diff --git a/src/master/master.cpp b/src/master/master.cpp
index e688b41..d53d6c2 100644
--- a/src/master/master.cpp
+++ b/src/master/master.cpp
@@ -1276,7 +1276,7 @@ Future<Option<Error> > Master::validate(
     << "Authorizing framework principal '" << frameworkInfo.principal()
     << "' to receive offers for role '" << frameworkInfo.role() << "'";
 
-  mesos::ACL::ReceiveOffers request;
+  mesos::ACL::RegisterFramework request;
   if (frameworkInfo.has_principal()) {
     request.mutable_principals()->add_values(frameworkInfo.principal());
   } else {
@@ -2286,7 +2286,7 @@ Future<Option<Error> > Master::validateTask(
     << "Authorizing framework principal '" << framework->info.principal()
     << "' to launch task " << task.task_id() << " as user '" << user << "'";
 
-  mesos::ACL::RunTasks request;
+  mesos::ACL::RunTask request;
   if (framework->info.has_principal()) {
     request.mutable_principals()->add_values(framework->info.principal());
   } else {

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/master/master.hpp
----------------------------------------------------------------------
diff --git a/src/master/master.hpp b/src/master/master.hpp
index 29e8f49..c9f989a 100644
--- a/src/master/master.hpp
+++ b/src/master/master.hpp
@@ -437,6 +437,16 @@ private:
     const static std::string TASKS_HELP;
 
   private:
+    // Helper for doing authentication, returns the credential used if
+    // the authentication was successful (or none if no credentials
+    // have been given to the master), otherwise an Error.
+    Result<Credential> authenticate(const process::http::Request& request);
+
+    // Continuations.
+    process::Future<process::http::Response> _shutdown(
+        const FrameworkID& id,
+        bool authorized = true);
+
     Master* master;
   } http;
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/sasl/authenticator.hpp
----------------------------------------------------------------------
diff --git a/src/sasl/authenticator.hpp b/src/sasl/authenticator.hpp
index aa222d3..35ab794 100644
--- a/src/sasl/authenticator.hpp
+++ b/src/sasl/authenticator.hpp
@@ -466,11 +466,11 @@ void load(const std::map<std::string, std::string>& secrets)
   InMemoryAuxiliaryPropertyPlugin::load(properties);
 }
 
-void load(const Credentials& c)
+void load(const Credentials& credentials)
 {
   std::map<std::string, std::string> secrets;
-  foreach(const Credential& registration, c.registration()) {
-    secrets[registration.principal()] = registration.secret();
+  foreach(const Credential& credential, credentials.credentials()) {
+    secrets[credential.principal()] = credential.secret();
   }
   load(secrets);
 }

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/tests/authorization_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/authorization_tests.cpp b/src/tests/authorization_tests.cpp
index 611f371..a8fa4cc 100644
--- a/src/tests/authorization_tests.cpp
+++ b/src/tests/authorization_tests.cpp
@@ -37,7 +37,7 @@ TEST_F(AuthorizationTest, AnyPrincipalRunAsUser)
 {
   // Any principal can run as "guest" user.
   ACLs acls;
-  mesos::ACL::RunTasks* acl = acls.add_run_tasks();
+  mesos::ACL::RunTask* acl = acls.add_run_tasks();
   acl->mutable_principals()->set_type(mesos::ACL::Entity::ANY);
   acl->mutable_users()->add_values("guest");
 
@@ -46,14 +46,14 @@ TEST_F(AuthorizationTest, AnyPrincipalRunAsUser)
   ASSERT_SOME(authorizer);
 
   // Principals "foo" and "bar" can run as "guest".
-  mesos::ACL::RunTasks request;
+  mesos::ACL::RunTask request;
   request.mutable_principals()->add_values("foo");
   request.mutable_principals()->add_values("bar");
   request.mutable_users()->add_values("guest");
   AWAIT_EXPECT_EQ(true, authorizer.get()->authorize(request));
 
   // Principal "foo" can run as "root" since the ACLs are permissive.
-  mesos::ACL::RunTasks request2;
+  mesos::ACL::RunTask request2;
   request2.mutable_principals()->add_values("foo");
   request2.mutable_users()->add_values("root");
   AWAIT_EXPECT_EQ(true, authorizer.get()->authorize(request2));
@@ -64,7 +64,7 @@ TEST_F(AuthorizationTest, NoPrincipalRunAsUser)
 {
   // No principal can run as "root" user.
   ACLs acls;
-  mesos::ACL::RunTasks* acl = acls.add_run_tasks();
+  mesos::ACL::RunTask* acl = acls.add_run_tasks();
   acl->mutable_principals()->set_type(mesos::ACL::Entity::NONE);
   acl->mutable_users()->add_values("root");
 
@@ -73,7 +73,7 @@ TEST_F(AuthorizationTest, NoPrincipalRunAsUser)
   ASSERT_SOME(authorizer);
 
   // Principal "foo" cannot run as "root".
-  mesos::ACL::RunTasks request;
+  mesos::ACL::RunTask request;
   request.mutable_principals()->add_values("foo");
   request.mutable_users()->add_values("root");
   AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request));
@@ -84,7 +84,7 @@ TEST_F(AuthorizationTest, PrincipalRunAsAnyUser)
 {
   // A principal "foo" can run as any user.
   ACLs acls;
-  mesos::ACL::RunTasks* acl = acls.add_run_tasks();
+  mesos::ACL::RunTask* acl = acls.add_run_tasks();
   acl->mutable_principals()->add_values("foo");
   acl->mutable_users()->set_type(mesos::ACL::Entity::ANY);
 
@@ -93,7 +93,7 @@ TEST_F(AuthorizationTest, PrincipalRunAsAnyUser)
   ASSERT_SOME(authorizer);
 
   // Principal "foo" can run as "user1" and "user2".
-  mesos::ACL::RunTasks request;
+  mesos::ACL::RunTask request;
   request.mutable_principals()->add_values("foo");
   request.mutable_users()->add_values("user1");
   request.mutable_users()->add_values("user2");
@@ -105,7 +105,7 @@ TEST_F(AuthorizationTest, AnyPrincipalRunAsAnyUser)
 {
   // Any principal can run as any user.
   ACLs acls;
-  mesos::ACL::RunTasks* acl = acls.add_run_tasks();
+  mesos::ACL::RunTask* acl = acls.add_run_tasks();
   acl->mutable_principals()->set_type(mesos::ACL::Entity::ANY);
   acl->mutable_users()->set_type(mesos::ACL::Entity::ANY);
 
@@ -114,7 +114,7 @@ TEST_F(AuthorizationTest, AnyPrincipalRunAsAnyUser)
   ASSERT_SOME(authorizer);
 
   // Principals "foo" and "bar" can run as "user1" and "user2".
-  mesos::ACL::RunTasks request;
+  mesos::ACL::RunTask request;
   request.mutable_principals()->add_values("foo");
   request.mutable_principals()->add_values("bar");
   request.mutable_users()->add_values("user1");
@@ -129,14 +129,14 @@ TEST_F(AuthorizationTest, OnlySomePrincipalsRunAsSomeUsers)
   ACLs acls;
 
   // ACL for some principals to run as some users.
-  mesos::ACL::RunTasks* acl = acls.add_run_tasks();
+  mesos::ACL::RunTask* acl = acls.add_run_tasks();
   acl->mutable_principals()->add_values("foo");
   acl->mutable_principals()->add_values("bar");
   acl->mutable_users()->add_values("user1");
   acl->mutable_users()->add_values("user2");
 
   // ACL for no one else to run as some users.
-  mesos::ACL::RunTasks* acl2 = acls.add_run_tasks();
+  mesos::ACL::RunTask* acl2 = acls.add_run_tasks();
   acl2->mutable_principals()->set_type(mesos::ACL::Entity::NONE);
   acl2->mutable_users()->add_values("user1");
   acl2->mutable_users()->add_values("user2");
@@ -146,7 +146,7 @@ TEST_F(AuthorizationTest, OnlySomePrincipalsRunAsSomeUsers)
   ASSERT_SOME(authorizer);
 
   // Principals "foo" and "bar" can run as "user1" and "user2".
-  mesos::ACL::RunTasks request;
+  mesos::ACL::RunTask request;
   request.mutable_principals()->add_values("foo");
   request.mutable_principals()->add_values("bar");
   request.mutable_users()->add_values("user1");
@@ -154,13 +154,13 @@ TEST_F(AuthorizationTest, OnlySomePrincipalsRunAsSomeUsers)
   AWAIT_EXPECT_EQ(true, authorizer.get()->authorize(request));
 
   // Principal "baz" cannot run as "user1".
-  mesos::ACL::RunTasks request2;
+  mesos::ACL::RunTask request2;
   request2.mutable_principals()->add_values("baz");
   request2.mutable_users()->add_values("user1");
   AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request2));
 
   // Principal "baz" cannot run as "user2".
-  mesos::ACL::RunTasks request3;
+  mesos::ACL::RunTask request3;
   request3.mutable_principals()->add_values("baz");
   request3.mutable_users()->add_values("user1");
   AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request3));
@@ -173,12 +173,12 @@ TEST_F(AuthorizationTest, SomePrincipalOnlySomeUser)
   ACLs acls;
 
   // ACL for some principal to run as some user.
-  mesos::ACL::RunTasks* acl = acls.add_run_tasks();
+  mesos::ACL::RunTask* acl = acls.add_run_tasks();
   acl->mutable_principals()->add_values("foo");
   acl->mutable_users()->add_values("user1");
 
   // ACL for some principal to not run as any other user.
-  mesos::ACL::RunTasks* acl2 = acls.add_run_tasks();
+  mesos::ACL::RunTask* acl2 = acls.add_run_tasks();
   acl2->mutable_principals()->add_values("foo");
   acl2->mutable_users()->set_type(mesos::ACL::Entity::NONE);
 
@@ -187,19 +187,19 @@ TEST_F(AuthorizationTest, SomePrincipalOnlySomeUser)
   ASSERT_SOME(authorizer);
 
   // Principal "foo" can run as "user1".
-  mesos::ACL::RunTasks request;
+  mesos::ACL::RunTask request;
   request.mutable_principals()->add_values("foo");
   request.mutable_users()->add_values("user1");
   AWAIT_EXPECT_EQ(true, authorizer.get()->authorize(request));
 
   // Principal "foo" cannot run as "user2".
-  mesos::ACL::RunTasks request2;
+  mesos::ACL::RunTask request2;
   request2.mutable_principals()->add_values("foo");
   request2.mutable_users()->add_values("user2");
   AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request2));
 
   // Principal "bar" can run as "user1" and "user2".
-  mesos::ACL::RunTasks request3;
+  mesos::ACL::RunTask request3;
   request3.mutable_principals()->add_values("bar");
   request3.mutable_users()->add_values("user1");
   request3.mutable_users()->add_values("user2");
@@ -212,7 +212,7 @@ TEST_F(AuthorizationTest, PrincipalRunAsSomeUserRestrictive)
   // A principal can run as "user1";
   ACLs acls;
   acls.set_permissive(false); // Restrictive.
-  mesos::ACL::RunTasks* acl = acls.add_run_tasks();
+  mesos::ACL::RunTask* acl = acls.add_run_tasks();
   acl->mutable_principals()->add_values("foo");
   acl->mutable_users()->add_values("user1");
 
@@ -221,19 +221,19 @@ TEST_F(AuthorizationTest, PrincipalRunAsSomeUserRestrictive)
   ASSERT_SOME(authorizer);
 
   // Principal "foo" can run as "user1".
-  mesos::ACL::RunTasks request;
+  mesos::ACL::RunTask request;
   request.mutable_principals()->add_values("foo");
   request.mutable_users()->add_values("user1");
   AWAIT_EXPECT_EQ(true, authorizer.get()->authorize(request));
 
   // Principal "foo" cannot run as "user2".
-  mesos::ACL::RunTasks request2;
+  mesos::ACL::RunTask request2;
   request2.mutable_principals()->add_values("foo");
   request2.mutable_users()->add_values("user2");
   AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request2));
 
   // Principal "bar" cannot run as "user2" since no ACL is set.
-  mesos::ACL::RunTasks request3;
+  mesos::ACL::RunTask request3;
   request3.mutable_principals()->add_values("bar");
   request3.mutable_users()->add_values("user2");
   AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request3));
@@ -244,7 +244,7 @@ TEST_F(AuthorizationTest, AnyPrincipalOfferedRole)
 {
   // Any principal can be offered "*" role's resources.
   ACLs acls;
-  mesos::ACL::ReceiveOffers* acl = acls.add_receive_offers();
+  mesos::ACL::RegisterFramework* acl = acls.add_register_frameworks();
   acl->mutable_principals()->set_type(mesos::ACL::Entity::ANY);
   acl->mutable_roles()->add_values("*");
 
@@ -253,7 +253,7 @@ TEST_F(AuthorizationTest, AnyPrincipalOfferedRole)
   ASSERT_SOME(authorizer);
 
   // Principals "foo" and "bar" can be offered "*" role's resources.
-  mesos::ACL::ReceiveOffers request;
+  mesos::ACL::RegisterFramework request;
   request.mutable_principals()->add_values("foo");
   request.mutable_principals()->add_values("bar");
   request.mutable_roles()->add_values("*");
@@ -265,7 +265,7 @@ TEST_F(AuthorizationTest, SomePrincipalsOfferedRole)
 {
   // Some principals can be offered "ads" role's resources.
   ACLs acls;
-  mesos::ACL::ReceiveOffers* acl = acls.add_receive_offers();
+  mesos::ACL::RegisterFramework* acl = acls.add_register_frameworks();
   acl->mutable_principals()->add_values("foo");
   acl->mutable_principals()->add_values("bar");
   acl->mutable_roles()->add_values("ads");
@@ -276,7 +276,7 @@ TEST_F(AuthorizationTest, SomePrincipalsOfferedRole)
 
   // Principals "foo", "bar" and "baz" (no ACL) can be offered "ads"
   // role's resources.
-  mesos::ACL::ReceiveOffers request;
+  mesos::ACL::RegisterFramework request;
   request.mutable_principals()->add_values("foo");
   request.mutable_principals()->add_values("bar");
   request.mutable_principals()->add_values("baz");
@@ -291,12 +291,12 @@ TEST_F(AuthorizationTest, PrincipalOfferedRole)
   ACLs acls;
 
   // ACL for a principal to be offered "analytics" role's resources.
-  mesos::ACL::ReceiveOffers* acl = acls.add_receive_offers();
+  mesos::ACL::RegisterFramework* acl = acls.add_register_frameworks();
   acl->mutable_principals()->add_values("foo");
   acl->mutable_roles()->add_values("analytics");
 
   // ACL for no one else to be offered "analytics" role's resources.
-  mesos::ACL::ReceiveOffers* acl2 = acls.add_receive_offers();
+  mesos::ACL::RegisterFramework* acl2 = acls.add_register_frameworks();
   acl2->mutable_principals()->set_type(mesos::ACL::Entity::NONE);
   acl2->mutable_roles()->add_values("analytics");
 
@@ -305,13 +305,13 @@ TEST_F(AuthorizationTest, PrincipalOfferedRole)
   ASSERT_SOME(authorizer);
 
   // Principal "foo" can be offered "analytics" role's resources.
-  mesos::ACL::ReceiveOffers request;
+  mesos::ACL::RegisterFramework request;
   request.mutable_principals()->add_values("foo");
   request.mutable_roles()->add_values("analytics");
   AWAIT_EXPECT_EQ(true, authorizer.get()->authorize(request));
 
   // Principal "bar" cannot be offered "analytics" role's resources.
-  mesos::ACL::ReceiveOffers request2;
+  mesos::ACL::RegisterFramework request2;
   request2.mutable_principals()->add_values("bar");
   request2.mutable_roles()->add_values("analytics");
   AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request2));
@@ -323,7 +323,7 @@ TEST_F(AuthorizationTest, PrincipalNotOfferedAnyRoleRestrictive)
   // A principal "foo" can be offered "analytics" role's resources.
   ACLs acls;
   acls.set_permissive(false);
-  mesos::ACL::ReceiveOffers* acl = acls.add_receive_offers();
+  mesos::ACL::RegisterFramework* acl = acls.add_register_frameworks();
   acl->mutable_principals()->add_values("foo");
   acl->mutable_roles()->add_values("analytics");
 
@@ -332,210 +332,20 @@ TEST_F(AuthorizationTest, PrincipalNotOfferedAnyRoleRestrictive)
   ASSERT_SOME(authorizer);
 
   // Principal "foo" can be offered "analytics" role's resources.
-  mesos::ACL::ReceiveOffers request;
+  mesos::ACL::RegisterFramework request;
   request.mutable_principals()->add_values("foo");
   request.mutable_roles()->add_values("analytics");
   AWAIT_EXPECT_EQ(true, authorizer.get()->authorize(request));
 
   // Principal "bar" cannot be offered "analytics" role's resources.
-  mesos::ACL::ReceiveOffers request2;
+  mesos::ACL::RegisterFramework request2;
   request2.mutable_principals()->add_values("bar");
   request2.mutable_roles()->add_values("analytics");
   AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request2));
 
   // Principal "bar" cannot be offered "ads" role's resources because no ACL.
-  mesos::ACL::ReceiveOffers request3;
+  mesos::ACL::RegisterFramework request3;
   request3.mutable_principals()->add_values("bar");
   request3.mutable_roles()->add_values("ads");
   AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request3));
 }
-
-
-TEST_F(AuthorizationTest, AnyClientGETSomeURL)
-{
-  // Any client can GET access "/help".
-  ACLs acls;
-  mesos::ACL::HTTPGet* acl = acls.add_http_get();
-  acl->mutable_usernames()->set_type(mesos::ACL::Entity::ANY);
-  acl->mutable_ips()->set_type(mesos::ACL::Entity::ANY);
-  acl->mutable_hostnames()->set_type(mesos::ACL::Entity::ANY);
-  acl->mutable_urls()->add_values("/help");
-
-  // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
-
-  // Clients "foo", "127.0.0.1", "localhost" can GET access "/help".
-  mesos::ACL::HTTPGet request;
-  request.mutable_usernames()->add_values("foo");
-  request.mutable_ips()->add_values("127.0.0.1");
-  request.mutable_hostnames()->add_values("localhost");
-  request.mutable_urls()->add_values("/help");
-  AWAIT_EXPECT_EQ(true, authorizer.get()->authorize(request));
-}
-
-
-TEST_F(AuthorizationTest, SomeClientsPUTSomeURL)
-{
-  // Only some clients can PUT access "/admin".
-  ACLs acls;
-
-  // Some clients can PUT access "/admin".
-  mesos::ACL::HTTPPut* acl = acls.add_http_put();
-  acl->mutable_ips()->add_values("127.0.0.1");
-  acl->mutable_hostnames()->add_values("localhost");
-  acl->mutable_urls()->add_values("/admin");
-
-  // No one else can PUT access "/admin".
-  mesos::ACL::HTTPPut* acl2 = acls.add_http_put();
-  acl2->mutable_usernames()->set_type(mesos::ACL::Entity::NONE);
-  acl2->mutable_ips()->set_type(mesos::ACL::Entity::NONE);
-  acl2->mutable_hostnames()->set_type(mesos::ACL::Entity::NONE);
-  acl2->mutable_urls()->add_values("/admin");
-
-  // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
-
-  // Clients "127.0.0.1" and "localhost" can PUT access "/admin".
-  mesos::ACL::HTTPPut request;
-  request.mutable_ips()->add_values("127.0.0.1");
-  request.mutable_hostnames()->add_values("localhost");
-  request.mutable_urls()->add_values("/admin");
-  AWAIT_EXPECT_EQ(true, authorizer.get()->authorize(request));
-
-  // Client "10.0.0.0" cannot PUT access "/admin".
-  mesos::ACL::HTTPPut request2;
-  request2.mutable_ips()->add_values("10.0.0.0");
-  request2.mutable_urls()->add_values("/admin");
-  AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request2));
-}
-
-
-TEST_F(AuthorizationTest, NoClientGETPUTSomeURL)
-{
-  // No client can GET access "/secret".
-  ACLs acls;
-  mesos::ACL::HTTPGet* acl = acls.add_http_get();
-  acl->mutable_usernames()->set_type(mesos::ACL::Entity::NONE);
-  acl->mutable_ips()->set_type(mesos::ACL::Entity::NONE);
-  acl->mutable_hostnames()->set_type(mesos::ACL::Entity::NONE);
-  acl->mutable_urls()->add_values("/secret");
-
-  // No client can PUT access "/secret".
-  mesos::ACL::HTTPPut* acl2 = acls.add_http_put();
-  acl2->mutable_usernames()->set_type(mesos::ACL::Entity::NONE);
-  acl2->mutable_ips()->set_type(mesos::ACL::Entity::NONE);
-  acl2->mutable_hostnames()->set_type(mesos::ACL::Entity::NONE);
-  acl2->mutable_urls()->add_values("/secret");
-
-  // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
-
-  // Clients "127.0.0.1" and "localhost" cannot GET access "/secret".
-  mesos::ACL::HTTPGet request;
-  request.mutable_ips()->add_values("127.0.0.1");
-  request.mutable_hostnames()->add_values("localhost");
-  request.mutable_urls()->add_values("/secret");
-  AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request));
-
-  // Clients "127.0.0.1" and "localhost" cannot PUT access "/secret".
-  mesos::ACL::HTTPPut request2;
-  request2.mutable_ips()->add_values("127.0.0.1");
-  request2.mutable_hostnames()->add_values("localhost");
-  request2.mutable_urls()->add_values("/secret");
-  AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request2));
-}
-
-
-TEST_F(AuthorizationTest, SomeClientsCannotGETAnyURL)
-{
-  // Some clients cannot GET access any URL.
-  ACLs acls;
-  mesos::ACL::HTTPGet* acl = acls.add_http_get();
-  acl->mutable_ips()->add_values("127.0.0.1");
-  acl->mutable_hostnames()->add_values("localhost");
-  acl->mutable_urls()->set_type(mesos::ACL::Entity::NONE);
-
-  // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
-
-  // Clients "127.0.0.1" and "localhost" cannot GET access "/help".
-  mesos::ACL::HTTPGet request;
-  request.mutable_ips()->add_values("127.0.0.1");
-  request.mutable_hostnames()->add_values("localhost");
-  request.mutable_urls()->add_values("/help");
-  AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request));
-}
-
-
-TEST_F(AuthorizationTest, NoClientsCanGETPUTAnyURLRestrictive)
-{
-  // No clients can GET/PUT access any URL.
-  ACLs acls;
-  acls.set_permissive(false);
-
-  // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
-
-  // Clients "foo", "127.0.0.1" cannot GET access "/help".
-  mesos::ACL::HTTPGet request;
-  request.mutable_usernames()->add_values("foo");
-  request.mutable_ips()->add_values("127.0.0.1");
-  request.mutable_urls()->add_values("/help");
-  AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request));
-
-  // Clients "127.0.0.1", "localhost" cannot PUT access "/help".
-  mesos::ACL::HTTPPut request2;
-  request2.mutable_ips()->add_values("127.0.0.1");
-  request2.mutable_hostnames()->add_values("localhost");
-  request2.mutable_urls()->add_values("/help");
-  AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request2));
-}
-
-
-TEST_F(AuthorizationTest, SomeClientsAggregatePUTRequestRestrictive)
-{
-  // Some clients can PUT access "/admin" but ACLs are setup
-  // separately.
-  ACLs acls;
-  acls.set_permissive(false);
-
-  // "foo" can PUT access "/admin".
-  mesos::ACL::HTTPPut* acl = acls.add_http_put();
-  acl->mutable_usernames()->add_values("foo");
-  acl->mutable_urls()->add_values("/admin");
-
-  // "bar" can PUT access "/admin".
-  mesos::ACL::HTTPPut* acl2 = acls.add_http_put();
-  acl2->mutable_usernames()->add_values("bar");
-  acl2->mutable_urls()->add_values("/admin");
-
-  // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
-
-  // "foo" can PUT access "/admin".
-  mesos::ACL::HTTPPut request;
-  request.mutable_usernames()->add_values("foo");
-  request.mutable_urls()->add_values("/admin");
-  AWAIT_EXPECT_EQ(true, authorizer.get()->authorize(request));
-
-  // "bar" can PUT access "/admin".
-  mesos::ACL::HTTPPut request2;
-  request2.mutable_usernames()->add_values("bar");
-  request2.mutable_urls()->add_values("/admin");
-  AWAIT_EXPECT_EQ(true, authorizer.get()->authorize(request2));
-
-  // Aggregate request for clients "foo" and "bar" for PUT access to
-  // "/admin" is not allowed because ACLs are not aggregated.
-  mesos::ACL::HTTPPut request3;
-  request3.mutable_usernames()->add_values("foo");
-  request3.mutable_usernames()->add_values("bar");
-  request3.mutable_urls()->add_values("/admin");
-  AWAIT_EXPECT_EQ(false, authorizer.get()->authorize(request3));
-}
-

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/tests/master_authorization_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_authorization_tests.cpp b/src/tests/master_authorization_tests.cpp
index 5c35577..f0f0648 100644
--- a/src/tests/master_authorization_tests.cpp
+++ b/src/tests/master_authorization_tests.cpp
@@ -72,7 +72,7 @@ TEST_F(MasterAuthorizationTest, AuthorizedTask)
 {
   // Setup ACLs so that the framework can launch tasks as "foo".
   ACLs acls;
-  mesos::ACL::RunTasks* acl = acls.add_run_tasks();
+  mesos::ACL::RunTask* acl = acls.add_run_tasks();
   acl->mutable_principals()->add_values(DEFAULT_FRAMEWORK_INFO.principal());
   acl->mutable_users()->add_values("foo");
 
@@ -150,7 +150,7 @@ TEST_F(MasterAuthorizationTest, UnauthorizedTask)
 {
   // Setup ACLs so that no framework can launch as "foo".
   ACLs acls;
-  mesos::ACL::RunTasks* acl = acls.add_run_tasks();
+  mesos::ACL::RunTask* acl = acls.add_run_tasks();
   acl->mutable_principals()->set_type(mesos::ACL::Entity::NONE);
   acl->mutable_users()->add_values("foo");
 
@@ -251,7 +251,7 @@ TEST_F(MasterAuthorizationTest, KillTask)
   // Return a pending future from authorizer.
   Future<Nothing> future;
   Promise<bool> promise;
-  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTask&>()))
     .WillOnce(DoAll(FutureSatisfy(&future),
                     Return(promise.future())));
 
@@ -325,7 +325,7 @@ TEST_F(MasterAuthorizationTest, SlaveRemoved)
   // Return a pending future from authorizer.
   Future<Nothing> future;
   Promise<bool> promise;
-  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTask&>()))
     .WillOnce(DoAll(FutureSatisfy(&future),
                     Return(promise.future())));
 
@@ -409,7 +409,7 @@ TEST_F(MasterAuthorizationTest, SlaveDisconnected)
   // Return a pending future from authorizer.
   Future<Nothing> future;
   Promise<bool> promise;
-  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTask&>()))
     .WillOnce(DoAll(FutureSatisfy(&future),
                     Return(promise.future())));
 
@@ -491,7 +491,7 @@ TEST_F(MasterAuthorizationTest, FrameworkRemoved)
   // Return a pending future from authorizer.
   Future<Nothing> future;
   Promise<bool> promise;
-  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTask&>()))
     .WillOnce(DoAll(FutureSatisfy(&future),
                     Return(promise.future())));
 
@@ -560,7 +560,7 @@ TEST_F(MasterAuthorizationTest, ReconcileTask)
   // Return a pending future from authorizer.
   Future<Nothing> future;
   Promise<bool> promise;
-  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTask&>()))
     .WillOnce(DoAll(FutureSatisfy(&future),
                     Return(promise.future())));
 
@@ -649,7 +649,7 @@ TEST_F(MasterAuthorizationTest, PendingExecutorInfoDiffersOnDifferentSlaves)
   // Return a pending future from authorizer.
   Future<Nothing> future;
   Promise<bool> promise;
-  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTask&>()))
     .WillOnce(DoAll(FutureSatisfy(&future),
                     Return(promise.future())));
 
@@ -694,7 +694,7 @@ TEST_F(MasterAuthorizationTest, PendingExecutorInfoDiffersOnDifferentSlaves)
   EXPECT_CALL(sched, statusUpdate(&driver, _))
     .WillOnce(FutureArg<1>(&status2));
 
-  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTask&>()))
     .WillOnce(Return(true));
 
   driver.launchTasks(offers2.get()[0].id(), tasks2);
@@ -738,7 +738,7 @@ TEST_F(MasterAuthorizationTest, AuthorizedRole)
   // Setup ACLs so that the framework can receive offers for role
   // "foo".
   ACLs acls;
-  mesos::ACL::ReceiveOffers* acl = acls.add_receive_offers();
+  mesos::ACL::RegisterFramework* acl = acls.add_register_frameworks();
   acl->mutable_principals()->add_values(DEFAULT_FRAMEWORK_INFO.principal());
   acl->mutable_roles()->add_values("foo");
 
@@ -779,7 +779,7 @@ TEST_F(MasterAuthorizationTest, UnauthorizedRole)
   // Setup ACLs so that no framework can receive offers for role
   // "foo".
   ACLs acls;
-  mesos::ACL::ReceiveOffers* acl = acls.add_receive_offers();
+  mesos::ACL::RegisterFramework* acl = acls.add_register_frameworks();
   acl->mutable_principals()->set_type(mesos::ACL::Entity::NONE);
   acl->mutable_roles()->add_values("foo");
 
@@ -840,7 +840,7 @@ TEST_F(MasterAuthorizationTest, DuplicateRegistration)
   Promise<bool> promise1;
   Future<Nothing> future2;
   Promise<bool> promise2;
-  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::ReceiveOffers&>()))
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RegisterFramework&>()))
     .WillOnce(DoAll(FutureSatisfy(&future1),
                     Return(promise1.future())))
     .WillOnce(DoAll(FutureSatisfy(&future2),
@@ -906,7 +906,7 @@ TEST_F(MasterAuthorizationTest, DuplicateReregistration)
   Promise<bool> promise2;
   Future<Nothing> future3;
   Promise<bool> promise3;
-  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::ReceiveOffers&>()))
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RegisterFramework&>()))
     .WillOnce(Return(true))
     .WillOnce(DoAll(FutureSatisfy(&future2),
                     Return(promise2.future())))
@@ -974,7 +974,7 @@ TEST_F(MasterAuthorizationTest, FrameworkRemovedBeforeRegistration)
   // Return a pending future from authorizer.
   Future<Nothing> future;
   Promise<bool> promise;
-  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::ReceiveOffers&>()))
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RegisterFramework&>()))
     .WillOnce(DoAll(FutureSatisfy(&future),
                     Return(promise.future())));
 
@@ -1032,7 +1032,7 @@ TEST_F(MasterAuthorizationTest, FrameworkRemovedBeforeReregistration)
   // Return a pending future from authorizer after first attempt.
   Future<Nothing> future2;
   Promise<bool> promise2;
-  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::ReceiveOffers&>()))
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RegisterFramework&>()))
     .WillOnce(Return(true))
     .WillOnce(DoAll(FutureSatisfy(&future2),
                     Return(promise2.future())));

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/tests/mesos.cpp
----------------------------------------------------------------------
diff --git a/src/tests/mesos.cpp b/src/tests/mesos.cpp
index 6b5c43f..5bd8ba0 100644
--- a/src/tests/mesos.cpp
+++ b/src/tests/mesos.cpp
@@ -101,10 +101,7 @@ master::Flags MesosTest::CreateMasterFlags()
 
   // JSON default format for credentials
   Credentials credentials;
-  Credential* credential = credentials.add_registration();
-  credential->set_principal(DEFAULT_CREDENTIAL.principal());
-  credential->set_secret(DEFAULT_CREDENTIAL.secret());
-  credential = credentials.add_http();
+  Credential* credential = credentials.add_credentials();
   credential->set_principal(DEFAULT_CREDENTIAL.principal());
   credential->set_secret(DEFAULT_CREDENTIAL.secret());
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/tests/mesos.hpp
----------------------------------------------------------------------
diff --git a/src/tests/mesos.hpp b/src/tests/mesos.hpp
index 8cf71d1..b31c347 100644
--- a/src/tests/mesos.hpp
+++ b/src/tests/mesos.hpp
@@ -492,27 +492,22 @@ public:
     // NOTE: We use 'EXPECT_CALL' and 'WillRepeatedly' here instead of
     // 'ON_CALL' and 'WillByDefault'. See 'TestContainerizer::SetUp()'
     // for more details.
-    EXPECT_CALL(*this, authorize(An<const mesos::ACL::RunTasks&>()))
+    EXPECT_CALL(*this, authorize(An<const mesos::ACL::RegisterFramework&>()))
       .WillRepeatedly(Return(true));
 
-    EXPECT_CALL(*this, authorize(An<const mesos::ACL::ReceiveOffers&>()))
+    EXPECT_CALL(*this, authorize(An<const mesos::ACL::RunTask&>()))
       .WillRepeatedly(Return(true));
 
-    EXPECT_CALL(*this, authorize(An<const mesos::ACL::HTTPGet&>()))
-      .WillRepeatedly(Return(true));
-
-    EXPECT_CALL(*this, authorize(An<const mesos::ACL::HTTPPut&>()))
+    EXPECT_CALL(*this, authorize(An<const mesos::ACL::ShutdownFramework&>()))
       .WillRepeatedly(Return(true));
   }
 
   MOCK_METHOD1(
-      authorize, process::Future<bool>(const ACL::RunTasks& request));
-  MOCK_METHOD1(
-      authorize, process::Future<bool>(const ACL::ReceiveOffers& request));
+      authorize, process::Future<bool>(const ACL::RegisterFramework& request));
   MOCK_METHOD1(
-      authorize, process::Future<bool>(const ACL::HTTPGet& request));
+      authorize, process::Future<bool>(const ACL::RunTask& request));
   MOCK_METHOD1(
-      authorize, process::Future<bool>(const ACL::HTTPPut& request));
+      authorize, process::Future<bool>(const ACL::ShutdownFramework& request));
 };
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/tests/reconciliation_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/reconciliation_tests.cpp b/src/tests/reconciliation_tests.cpp
index 952f29b..3c4d7ed 100644
--- a/src/tests/reconciliation_tests.cpp
+++ b/src/tests/reconciliation_tests.cpp
@@ -622,7 +622,7 @@ TEST_F(ReconciliationTest, PendingTask)
   // Return a pending future from authorizer.
   Future<Nothing> future;
   Promise<bool> promise;
-  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTask&>()))
     .WillOnce(DoAll(FutureSatisfy(&future),
                     Return(promise.future())));
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/tests/script.cpp
----------------------------------------------------------------------
diff --git a/src/tests/script.cpp b/src/tests/script.cpp
index 3129479..515e314 100644
--- a/src/tests/script.cpp
+++ b/src/tests/script.cpp
@@ -135,16 +135,16 @@ void execute(const string& script)
     ACLs acls;
     acls.set_permissive(false);
 
-    mesos::ACL::RunTasks* run = acls.add_run_tasks();
+    mesos::ACL::RunTask* run = acls.add_run_tasks();
     run->mutable_principals()->add_values(DEFAULT_CREDENTIAL.principal());
 
     Result<string> user = os::user();
     CHECK_SOME(user) << "Failed to get current user name";
     run->mutable_users()->add_values(user.get());
 
-    mesos::ACL::ReceiveOffers* offer = acls.add_receive_offers();
-    offer->mutable_principals()->add_values(DEFAULT_CREDENTIAL.principal());
-    offer->mutable_roles()->add_values("*");
+    mesos::ACL::RegisterFramework* register_ = acls.add_register_frameworks();
+    register_->mutable_principals()->add_values(DEFAULT_CREDENTIAL.principal());
+    register_->mutable_roles()->add_values("*");
 
     const string& aclsPath = path::join(directory.get(), "acls");
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/a5cc9b43/src/tests/shutdown_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/shutdown_tests.cpp b/src/tests/shutdown_tests.cpp
index ad13aa1..12ebef4 100644
--- a/src/tests/shutdown_tests.cpp
+++ b/src/tests/shutdown_tests.cpp
@@ -64,9 +64,9 @@ using testing::Return;
 class ShutdownTest : public MesosTest {};
 
 // Testing /master/shutdown so this endopoint  shuts down
-// designated framework or return adequate error
+// designated framework or return adequate error.
 
-// Testing route with authorization header and good credentials
+// Testing route with authorization header and good credentials.
 TEST_F(ShutdownTest, ShutdownEndpoint)
 {
   Try<PID<Master> > master = StartMaster();
@@ -105,7 +105,7 @@ TEST_F(ShutdownTest, ShutdownEndpoint)
 }
 
 
-// Testing route with bad credentials
+// Testing route with bad credentials.
 TEST_F(ShutdownTest, ShutdownEndpointBadCredentials)
 {
   Try<PID<Master> > master = StartMaster();
@@ -145,7 +145,106 @@ TEST_F(ShutdownTest, ShutdownEndpointBadCredentials)
 }
 
 
-// Testing route without frameworkId value
+// Testing route with good ACLs.
+TEST_F(ShutdownTest, ShutdownEndpointGoodACLs)
+{
+  // Setup ACLs so that the default principal can shutdown the
+  // framework.
+  ACLs acls;
+  mesos::ACL::ShutdownFramework* acl = acls.add_shutdown_frameworks();
+  acl->mutable_principals()->add_values(DEFAULT_CREDENTIAL.principal());
+  acl->mutable_framework_principals()->add_values(
+      DEFAULT_CREDENTIAL.principal());
+
+  master::Flags flags = CreateMasterFlags();
+  flags.acls = acls;
+  Try<PID<Master> > master = StartMaster(flags);
+  ASSERT_SOME(master);
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
+
+  Future<FrameworkID> frameworkId;
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .WillOnce(FutureArg<1>(&frameworkId));
+
+  ASSERT_EQ(DRIVER_RUNNING, driver.start());
+
+  AWAIT_READY(frameworkId);
+
+  hashmap<string, string> headers;
+  headers["Authorization"] = "Basic " +
+    base64::encode(DEFAULT_CREDENTIAL.principal() +
+                   ":" + DEFAULT_CREDENTIAL.secret());
+
+  Future<Response> response = process::http::post(
+      master.get(),
+      "shutdown",
+      headers,
+      "frameworkId=" + frameworkId.get().value());
+
+  AWAIT_READY(response);
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+  driver.stop();
+  driver.join();
+
+  Shutdown();
+}
+
+
+// Testing route with bad ACLs.
+TEST_F(ShutdownTest, ShutdownEndpointBadACLs)
+{
+  // Setup ACLs so that no principal can do shutdown the framework.
+  ACLs acls;
+  mesos::ACL::ShutdownFramework* acl = acls.add_shutdown_frameworks();
+  acl->mutable_principals()->set_type(mesos::ACL::Entity::NONE);
+  acl->mutable_framework_principals()->add_values(
+      DEFAULT_CREDENTIAL.principal());
+
+  master::Flags flags = CreateMasterFlags();
+  flags.acls = acls;
+  Try<PID<Master> > master = StartMaster(flags);
+  ASSERT_SOME(master);
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
+
+  Future<FrameworkID> frameworkId;
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .WillOnce(FutureArg<1>(&frameworkId));
+
+  ASSERT_EQ(DRIVER_RUNNING, driver.start());
+
+  AWAIT_READY(frameworkId);
+
+  hashmap<string, string> headers;
+  headers["Authorization"] = "Basic " +
+    base64::encode(DEFAULT_CREDENTIAL.principal() +
+                   ":" + DEFAULT_CREDENTIAL.secret());
+
+  Future<Response> response = process::http::post(
+      master.get(),
+      "shutdown",
+      headers,
+      "frameworkId=" + frameworkId.get().value());
+
+  AWAIT_READY(response);
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(
+      Unauthorized("Mesos master").status,
+      response);
+
+  driver.stop();
+  driver.join();
+
+  Shutdown();
+}
+
+
+// Testing route without frameworkId value.
 TEST_F(ShutdownTest, ShutdownEndpointNoFrameworkId)
 {
   Try<PID<Master> > master = StartMaster();
@@ -177,7 +276,7 @@ TEST_F(ShutdownTest, ShutdownEndpointNoFrameworkId)
 }
 
 
-// Testing route without authorization header
+// Testing route without authorization header.
 TEST_F(ShutdownTest, ShutdownEndpointNoHeader)
 {
   Try<PID<Master> > master = StartMaster();


[2/2] git commit: Added overloads to 'process::defer()' to dispatch lambda function to a specific pid.

Posted by vi...@apache.org.
Added overloads to 'process::defer()' to dispatch lambda function
to a specific pid.


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/94b94393
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/94b94393
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/94b94393

Branch: refs/heads/master
Commit: 94b9439371db9e8e7e3a102fdbe73b80a1da6a8b
Parents: 52cf9b3
Author: Benjamin Hindman <be...@gmail.com>
Authored: Fri Aug 8 16:51:23 2014 -0700
Committer: Vinod Kone <vi...@gmail.com>
Committed: Fri Aug 8 17:03:17 2014 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/include/process/defer.hpp   | 36 ++++++++++++++++++++
 .../libprocess/include/process/deferred.hpp     | 17 ++++++++-
 2 files changed, 52 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/94b94393/3rdparty/libprocess/include/process/defer.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/defer.hpp b/3rdparty/libprocess/include/process/defer.hpp
index dc2ec3b..dce7f3b 100644
--- a/3rdparty/libprocess/include/process/defer.hpp
+++ b/3rdparty/libprocess/include/process/defer.hpp
@@ -384,6 +384,18 @@ inline void dispatcher(
 
 
 // Now we define defer calls for functions and bind statements.
+inline Deferred<void(void)> defer(
+    const UPID& pid,
+    const std::tr1::function<void(void)>& f)
+{
+  return std::tr1::function<void(void)>(
+      std::tr1::bind(&internal::dispatcher,
+                     pid,
+                     f));
+}
+
+
+// Now we define defer calls for functions and bind statements.
 inline Deferred<void(void)> defer(const std::tr1::function<void(void)>& f)
 {
   if (__process__ != NULL) {
@@ -405,6 +417,18 @@ inline Deferred<void(void)> defer(const std::tr1::function<void(void)>& f)
 #define TEMPLATE(Z, N, DATA)                                            \
   template <ENUM_PARAMS(N, typename A)>                                 \
   Deferred<void(ENUM_PARAMS(N, A))> defer(                              \
+      const UPID& pid,                                                  \
+      const std::tr1::function<void(ENUM_PARAMS(N, A))>& f)             \
+  {                                                                     \
+    return std::tr1::function<void(ENUM_PARAMS(N, A))>(                 \
+        std::tr1::bind(&internal::CAT(dispatcher, N)<ENUM_PARAMS(N, A)>, \
+                       pid,                                             \
+                       f,                                               \
+                       ENUM_BINARY_PARAMS(N, internal::_, () INTERCEPT))); \
+  }                                                                     \
+                                                                        \
+  template <ENUM_PARAMS(N, typename A)>                                 \
+  Deferred<void(ENUM_PARAMS(N, A))> defer(                              \
       const std::tr1::function<void(ENUM_PARAMS(N, A))>& f)             \
   {                                                                     \
     if (__process__ != NULL) {                                          \
@@ -420,6 +444,18 @@ inline Deferred<void(void)> defer(const std::tr1::function<void(void)>& f)
                                                                         \
   template <typename R, ENUM_PARAMS(N, typename A)>                     \
   Deferred<Future<R>(ENUM_PARAMS(N, A))> defer(                         \
+      const UPID& pid,                                                  \
+      const std::tr1::function<Future<R>(ENUM_PARAMS(N, A))>& f)        \
+  {                                                                     \
+    return std::tr1::function<Future<R>(ENUM_PARAMS(N, A))>(            \
+        std::tr1::bind(&internal::CAT(dispatcher, N)<ENUM_PARAMS(N, A)>, \
+                       pid,                                             \
+                       f,                                               \
+                       ENUM_BINARY_PARAMS(N, internal::_, () INTERCEPT))); \
+  }                                                                     \
+                                                                        \
+  template <typename R, ENUM_PARAMS(N, typename A)>                     \
+  Deferred<Future<R>(ENUM_PARAMS(N, A))> defer(                         \
       const std::tr1::function<Future<R>(ENUM_PARAMS(N, A))>& f)        \
   {                                                                     \
     if (__process__ != NULL) {                                          \

http://git-wip-us.apache.org/repos/asf/mesos/blob/94b94393/3rdparty/libprocess/include/process/deferred.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/deferred.hpp b/3rdparty/libprocess/include/process/deferred.hpp
index 0552fb5..8bdc692 100644
--- a/3rdparty/libprocess/include/process/deferred.hpp
+++ b/3rdparty/libprocess/include/process/deferred.hpp
@@ -31,15 +31,30 @@ private:
 
   template <typename _F> friend struct _Defer;
 
-  friend Deferred<void(void)> defer(const std::tr1::function<void(void)>& f);
+  friend Deferred<void(void)> defer(
+      const UPID& pid,
+      const std::tr1::function<void(void)>& f);
+
+  friend Deferred<void(void)> defer(
+      const std::tr1::function<void(void)>& f);
 
 #define TEMPLATE(Z, N, DATA)                                            \
   template <ENUM_PARAMS(N, typename A)>                                 \
   friend Deferred<void(ENUM_PARAMS(N, A))> defer(                       \
+      const UPID& pid,                                                  \
+      const std::tr1::function<void(ENUM_PARAMS(N, A))>& f);            \
+                                                                        \
+  template <ENUM_PARAMS(N, typename A)>                                 \
+  friend Deferred<void(ENUM_PARAMS(N, A))> defer(                       \
       const std::tr1::function<void(ENUM_PARAMS(N, A))>& f);            \
                                                                         \
   template <typename R, ENUM_PARAMS(N, typename A)>                     \
   friend Deferred<Future<R>(ENUM_PARAMS(N, A))> defer(                  \
+      const UPID& pid,                                                  \
+      const std::tr1::function<Future<R>(ENUM_PARAMS(N, A))>& f);       \
+                                                                        \
+  template <typename R, ENUM_PARAMS(N, typename A)>                     \
+  friend Deferred<Future<R>(ENUM_PARAMS(N, A))> defer(                  \
       const std::tr1::function<Future<R>(ENUM_PARAMS(N, A))>& f);
 
   REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9.