http://git-wip-us.apache.org/repos/asf/mesos/blob/dc1e188a/src/master/http.cpp
----------------------------------------------------------------------
diff --git a/src/master/http.cpp b/src/master/http.cpp
index 05fd7ce..1d7e159 100644
--- a/src/master/http.cpp
+++ b/src/master/http.cpp
@@ -125,11 +125,22 @@ using std::tie;
 using std::tuple;
 using std::vector;
 
+using mesos::authorization::createSubject;
+using mesos::authorization::GET_MAINTENANCE_SCHEDULE;
+using mesos::authorization::GET_MAINTENANCE_STATUS;
+using mesos::authorization::MARK_AGENT_GONE;
+using mesos::authorization::SET_LOG_LEVEL;
+using mesos::authorization::START_MAINTENANCE;
+using mesos::authorization::STOP_MAINTENANCE;
+using mesos::authorization::UPDATE_MAINTENANCE_SCHEDULE;
+using mesos::authorization::VIEW_EXECUTOR;
+using mesos::authorization::VIEW_FLAGS;
+using mesos::authorization::VIEW_FRAMEWORK;
+using mesos::authorization::VIEW_ROLE;
+using mesos::authorization::VIEW_TASK;
 
 namespace mesos {
 
-using mesos::authorization::createSubject;
-
 static void json(
     JSON::StringWriter* writer,
     const FrameworkInfo::Capability& capability)
@@ -228,11 +239,9 @@ static void json(JSON::ObjectWriter* writer, const 
Summary<Framework>& summary);
 // user is authorized to view them.
 struct FullFrameworkWriter {
   FullFrameworkWriter(
-      const Owned<AuthorizationAcceptor>& authorizeTask,
-      const Owned<AuthorizationAcceptor>& authorizeExecutorInfo,
+      const Owned<ObjectApprovers>& approvers,
       const Framework* framework)
-    : authorizeTask_(authorizeTask),
-      authorizeExecutorInfo_(authorizeExecutorInfo),
+    : approvers_(approvers),
       framework_(framework) {}
 
   void operator()(JSON::ObjectWriter* writer) const
@@ -277,7 +286,7 @@ struct FullFrameworkWriter {
     writer->field("tasks", [this](JSON::ArrayWriter* writer) {
       foreachvalue (const TaskInfo& taskInfo, framework_->pendingTasks) {
         // Skip unauthorized tasks.
-        if (!authorizeTask_->accept(taskInfo, framework_->info)) {
+        if (!approvers_->approved<VIEW_TASK>(taskInfo, framework_->info)) {
           continue;
         }
 
@@ -318,7 +327,7 @@ struct FullFrameworkWriter {
 
       foreachvalue (Task* task, framework_->tasks) {
         // Skip unauthorized tasks.
-        if (!authorizeTask_->accept(*task, framework_->info)) {
+        if (!approvers_->approved<VIEW_TASK>(*task, framework_->info)) {
           continue;
         }
 
@@ -329,7 +338,7 @@ struct FullFrameworkWriter {
     writer->field("unreachable_tasks", [this](JSON::ArrayWriter* writer) {
       foreachvalue (const Owned<Task>& task, framework_->unreachableTasks) {
         // Skip unauthorized tasks.
-        if (!authorizeTask_->accept(*task, framework_->info)) {
+        if (!approvers_->approved<VIEW_TASK>(*task, framework_->info)) {
           continue;
         }
 
@@ -340,7 +349,7 @@ struct FullFrameworkWriter {
     writer->field("completed_tasks", [this](JSON::ArrayWriter* writer) {
       foreach (const Owned<Task>& task, framework_->completedTasks) {
         // Skip unauthorized tasks.
-        if (!authorizeTask_->accept(*task, framework_->info)) {
+        if (!approvers_->approved<VIEW_TASK>(*task, framework_->info)) {
           continue;
         }
 
@@ -366,7 +375,8 @@ struct FullFrameworkWriter {
                            &executor,
                            &slaveId](JSON::ObjectWriter* writer) {
             // Skip unauthorized executors.
-            if (!authorizeExecutorInfo_->accept(executor, framework_->info)) {
+            if (!approvers_->approved<VIEW_EXECUTOR>(
+                    executor, framework_->info)) {
               return;
             }
 
@@ -383,8 +393,7 @@ struct FullFrameworkWriter {
     }
   }
 
-  const Owned<AuthorizationAcceptor>& authorizeTask_;
-  const Owned<AuthorizationAcceptor>& authorizeExecutorInfo_;
+  const Owned<ObjectApprovers>& approvers_;
   const Framework* framework_;
 };
 
@@ -393,8 +402,8 @@ struct SlaveWriter
 {
   SlaveWriter(
       const Slave& slave,
-      const Owned<AuthorizationAcceptor>& authorizeRole)
-    : slave_(slave), authorizeRole_(authorizeRole) {}
+      const Owned<ObjectApprovers>& approvers)
+    : slave_(slave), approvers_(approvers) {}
 
   void operator()(JSON::ObjectWriter* writer) const
   {
@@ -419,7 +428,7 @@ struct SlaveWriter
             // TODO(arojas): Consider showing unapproved resources in an
             // aggregated special field, so that all resource values add up
             // MESOS-7779.
-            if (authorizeRole_->accept(role)) {
+            if (approvers_->approved<VIEW_ROLE>(role)) {
               writer->field(role, reservation);
             }
           }
@@ -432,7 +441,7 @@ struct SlaveWriter
   }
 
   const Slave& slave_;
-  const Owned<AuthorizationAcceptor>& authorizeRole_;
+  const Owned<ObjectApprovers>& approvers_;
 };
 
 
@@ -440,10 +449,10 @@ struct SlavesWriter
 {
   SlavesWriter(
       const Master::Slaves& slaves,
-      const Owned<AuthorizationAcceptor>& authorizeRole,
+      const Owned<ObjectApprovers>& approvers,
       const IDAcceptor<SlaveID>& selectSlaveId)
     : slaves_(slaves),
-      authorizeRole_(authorizeRole),
+      approvers_(approvers),
       selectSlaveId_(selectSlaveId) {}
 
   void operator()(JSON::ObjectWriter* writer) const
@@ -475,7 +484,7 @@ struct SlavesWriter
 
   void writeSlave(const Slave* slave, JSON::ObjectWriter* writer) const
   {
-    SlaveWriter(*slave, authorizeRole_)(writer);
+    SlaveWriter(*slave, approvers_)(writer);
 
     // Add the complete protobuf->JSON for all used, reserved,
     // and offered resources. The other endpoints summarize
@@ -492,11 +501,11 @@ struct SlavesWriter
           foreachpair (const string& role,
                        const Resources& resources,
                        reserved) {
-            if (authorizeRole_->accept(role)) {
+            if (approvers_->approved<VIEW_ROLE>(role)) {
               writer->field(role, [&resources, this](
                   JSON::ArrayWriter* writer) {
                 foreach (Resource resource, resources) {
-                  if (authorizeResource(resource, authorizeRole_)) {
+                  if (approvers_->approved<VIEW_ROLE>(resource)) {
                     convertResourceFormat(&resource, ENDPOINT);
                     writer->element(JSON::Protobuf(resource));
                   }
@@ -512,7 +521,7 @@ struct SlavesWriter
         "unreserved_resources_full",
         [&unreservedResources, this](JSON::ArrayWriter* writer) {
           foreach (Resource resource, unreservedResources) {
-            if (authorizeResource(resource, authorizeRole_)) {
+            if (approvers_->approved<VIEW_ROLE>(resource)) {
               convertResourceFormat(&resource, ENDPOINT);
               writer->element(JSON::Protobuf(resource));
             }
@@ -525,7 +534,7 @@ struct SlavesWriter
         "used_resources_full",
         [&usedResources, this](JSON::ArrayWriter* writer) {
           foreach (Resource resource, usedResources) {
-            if (authorizeResource(resource, authorizeRole_)) {
+            if (approvers_->approved<VIEW_ROLE>(resource)) {
               convertResourceFormat(&resource, ENDPOINT);
               writer->element(JSON::Protobuf(resource));
             }
@@ -538,7 +547,7 @@ struct SlavesWriter
         "offered_resources_full",
         [&offeredResources, this](JSON::ArrayWriter* writer) {
           foreach (Resource resource, offeredResources) {
-            if (authorizeResource(resource, authorizeRole_)) {
+            if (approvers_->approved<VIEW_ROLE>(resource)) {
               convertResourceFormat(&resource, ENDPOINT);
               writer->element(JSON::Protobuf(resource));
             }
@@ -547,7 +556,7 @@ struct SlavesWriter
   }
 
   const Master::Slaves& slaves_;
-  const Owned<AuthorizationAcceptor>& authorizeRole_;
+  const Owned<ObjectApprovers>& approvers_;
   const IDAcceptor<SlaveID>& selectSlaveId_;
 };
 
@@ -806,51 +815,13 @@ Future<Response> Master::Http::subscribe(
 {
   CHECK_EQ(mesos::master::Call::SUBSCRIBE, call.type());
 
-  // Retrieve Approvers for authorizing frameworks and tasks.
-  Future<Owned<ObjectApprover>> frameworksApprover;
-  Future<Owned<ObjectApprover>> tasksApprover;
-  Future<Owned<ObjectApprover>> executorsApprover;
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    frameworksApprover = master->authorizer.get()->getObjectApprover(
-        subject, authorization::VIEW_FRAMEWORK);
-
-    tasksApprover = master->authorizer.get()->getObjectApprover(
-        subject, authorization::VIEW_TASK);
-
-    executorsApprover = master->authorizer.get()->getObjectApprover(
-        subject, authorization::VIEW_EXECUTOR);
-  } else {
-    frameworksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover());
-    tasksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover());
-    executorsApprover = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  Future<Owned<AuthorizationAcceptor>> rolesAcceptor =
-    AuthorizationAcceptor::create(
-        principal,
-        master->authorizer,
-        authorization::VIEW_ROLE);
-
-  return collect(
-      frameworksApprover, tasksApprover, executorsApprover, rolesAcceptor)
-    .then(defer(master->self(),
-        [=](const tuple<Owned<ObjectApprover>,
-                        Owned<ObjectApprover>,
-                        Owned<ObjectApprover>,
-                        Owned<AuthorizationAcceptor>>& approvers)
-            -> Future<Response> {
-          // Get approver from tuple.
-          Owned<ObjectApprover> frameworksApprover;
-          Owned<ObjectApprover> tasksApprover;
-          Owned<ObjectApprover> executorsApprover;
-          Owned<AuthorizationAcceptor> rolesAcceptor;
-          tie(frameworksApprover,
-              tasksApprover,
-              executorsApprover,
-              rolesAcceptor) = approvers;
-
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {VIEW_FRAMEWORK, VIEW_TASK, VIEW_EXECUTOR, VIEW_ROLE})
+    .then(defer(
+        master->self(),
+        [=](const Owned<ObjectApprovers>& approvers) -> Future<Response> {
           Pipe pipe;
           OK ok;
 
@@ -864,11 +835,7 @@ Future<Response> Master::Http::subscribe(
           mesos::master::Event event;
           event.set_type(mesos::master::Event::SUBSCRIBED);
           *event.mutable_subscribed()->mutable_get_state() =
-              _getState(
-                  frameworksApprover,
-                  tasksApprover,
-                  executorsApprover,
-                  rolesAcceptor);
+            _getState(approvers);
 
           event.mutable_subscribed()->set_heartbeat_interval_seconds(
               DEFAULT_HEARTBEAT_INTERVAL.secs());
@@ -880,7 +847,7 @@ Future<Response> Master::Http::subscribe(
           http.send<mesos::master::Event, v1::master::Event>(heartbeatEvent);
 
           return ok;
-    }));
+        }));
 }
 
 
@@ -1556,97 +1523,63 @@ Future<Response> Master::Http::frameworks(
     return redirect(request);
   }
 
-  Future<Owned<AuthorizationAcceptor>> authorizeFrameworkInfo =
-    AuthorizationAcceptor::create(
-        principal, master->authorizer, authorization::VIEW_FRAMEWORK);
-  Future<Owned<AuthorizationAcceptor>> authorizeTask =
-    AuthorizationAcceptor::create(
-        principal, master->authorizer, authorization::VIEW_TASK);
-  Future<Owned<AuthorizationAcceptor>> authorizeExecutorInfo =
-    AuthorizationAcceptor::create(
-        principal, master->authorizer, authorization::VIEW_EXECUTOR);
-  Future<IDAcceptor<FrameworkID>> selectFrameworkId =
-    IDAcceptor<FrameworkID>(request.url.query.get("framework_id"));
-
-  return collect(
-      authorizeFrameworkInfo,
-      authorizeTask,
-      authorizeExecutorInfo,
-      selectFrameworkId)
-    .then(defer(master->self(),
-        [this, request](const tuple<Owned<AuthorizationAcceptor>,
-                                    Owned<AuthorizationAcceptor>,
-                                    Owned<AuthorizationAcceptor>,
-                                    IDAcceptor<FrameworkID>>& acceptors)
-          -> Response {
-      // This lambda is consumed before the outer lambda
-      // returns, hence capture by reference is fine here.
-      auto frameworks = [this, &acceptors](JSON::ObjectWriter* writer) {
-        Owned<AuthorizationAcceptor> authorizeFrameworkInfo;
-        Owned<AuthorizationAcceptor> authorizeTask;
-        Owned<AuthorizationAcceptor> authorizeExecutorInfo;
-        IDAcceptor<FrameworkID> selectFrameworkId;
-        tie(authorizeFrameworkInfo,
-            authorizeTask,
-            authorizeExecutorInfo,
-            selectFrameworkId) = acceptors;
-
-        // Model all of the frameworks.
-        writer->field(
-            "frameworks",
-            [this,
-             &authorizeFrameworkInfo,
-             &authorizeTask,
-             &authorizeExecutorInfo,
-             &selectFrameworkId](JSON::ArrayWriter* writer) {
-          foreachvalue (Framework* framework, master->frameworks.registered) {
-            // Skip unauthorized frameworks or frameworks without a matching 
ID.
-            if (!selectFrameworkId.accept(framework->id()) ||
-                !authorizeFrameworkInfo->accept(framework->info)) {
-              continue;
-            }
-
-            FullFrameworkWriter frameworkWriter(
-                authorizeTask,
-                authorizeExecutorInfo,
-                framework);
-
-            writer->element(frameworkWriter);
-          }
-        });
-
-        // Model all of the completed frameworks.
-        writer->field(
-            "completed_frameworks",
-            [this,
-             &authorizeFrameworkInfo,
-             &authorizeTask,
-             &authorizeExecutorInfo,
-             &selectFrameworkId](JSON::ArrayWriter* writer) {
-          foreachvalue (const Owned<Framework>& framework,
-                        master->frameworks.completed) {
-            // Skip unauthorized frameworks or frameworks without a matching 
ID.
-            if (!selectFrameworkId.accept(framework->id()) ||
-                !authorizeFrameworkInfo->accept(framework->info)) {
-              continue;
-            }
-
-            FullFrameworkWriter frameworkWriter(
-                authorizeTask,
-                authorizeExecutorInfo,
-                framework.get());
-
-            writer->element(frameworkWriter);
-          }
-        });
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {VIEW_FRAMEWORK, VIEW_TASK, VIEW_EXECUTOR})
+    .then(defer(
+        master->self(),
+        [this, request](const Owned<ObjectApprovers>& approvers) -> Response {
+          IDAcceptor<FrameworkID> selectFrameworkId(
+              request.url.query.get("framework_id"));
+          // This lambda is consumed before the outer lambda
+          // returns, hence capture by reference is fine here.
+          auto frameworks = [this, &approvers, &selectFrameworkId](
+              JSON::ObjectWriter* writer) {
+            // Model all of the frameworks.
+            writer->field(
+                "frameworks",
+                [this, &approvers, &selectFrameworkId](
+                    JSON::ArrayWriter* writer) {
+                  foreachvalue (
+                      Framework* framework, master->frameworks.registered) {
+                    // Skip unauthorized frameworks or frameworks
+                    // without a matching ID.
+                    if (!selectFrameworkId.accept(framework->id()) ||
+                        !approvers->approved<VIEW_FRAMEWORK>(framework->info)) 
{
+                      continue;
+                    }
+
+                    writer->element(FullFrameworkWriter(approvers, framework));
+                  }
+                });
+
+            // Model all of the completed frameworks.
+            writer->field(
+                "completed_frameworks",
+                [this, &approvers, &selectFrameworkId](
+                    JSON::ArrayWriter* writer) {
+                  foreachvalue (const Owned<Framework>& framework,
+                                master->frameworks.completed) {
+                    // Skip unauthorized frameworks or frameworks
+                    // without a matching ID.
+                    if (!selectFrameworkId.accept(framework->id()) ||
+                        !approvers->approved<VIEW_FRAMEWORK>(framework->info)) 
{
+                      continue;
+                    }
+
+                    writer->element(
+                        FullFrameworkWriter(approvers, framework.get()));
+                  }
+                });
 
-        // Unregistered frameworks are no longer possible. We emit an
-        // empty array for the sake of backward compatibility.
-        writer->field("unregistered_frameworks", [](JSON::ArrayWriter*) {});
-      };
+            // Unregistered frameworks are no longer possible. We emit an
+            // empty array for the sake of backward compatibility.
+            writer->field("unregistered_frameworks", [](JSON::ArrayWriter*) 
{});
+          };
 
-      return OK(jsonify(frameworks), request.url.query.get("jsonp"));
-  }));
+          return OK(jsonify(frameworks), request.url.query.get("jsonp"));
+        }));
 }
 
 
@@ -1707,40 +1640,31 @@ Future<Response> Master::Http::getFrameworks(
 {
   CHECK_EQ(mesos::master::Call::GET_FRAMEWORKS, call.type());
 
-  // Retrieve `ObjectApprover`s for authorizing frameworks.
-  Future<Owned<ObjectApprover>> frameworksApprover;
-
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    frameworksApprover = master->authorizer.get()->getObjectApprover(
-        subject, authorization::VIEW_FRAMEWORK);
-  } else {
-    frameworksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  return frameworksApprover
-    .then(defer(master->self(),
-        [=](const Owned<ObjectApprover>& frameworksApprover)
-          -> Future<Response> {
-      mesos::master::Response response;
-      response.set_type(mesos::master::Response::GET_FRAMEWORKS);
-      *response.mutable_get_frameworks() = _getFrameworks(frameworksApprover);
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {VIEW_FRAMEWORK})
+    .then(defer(
+        master->self(),
+        [=](const Owned<ObjectApprovers>& approvers) -> Future<Response> {
+          mesos::master::Response response;
+          response.set_type(mesos::master::Response::GET_FRAMEWORKS);
+          *response.mutable_get_frameworks() = _getFrameworks(approvers);
 
-      return OK(serialize(contentType, evolve(response)),
-                stringify(contentType));
-    }));
+          return OK(
+              serialize(contentType, evolve(response)), 
stringify(contentType));
+        }));
 }
 
 
 mesos::master::Response::GetFrameworks Master::Http::_getFrameworks(
-    const Owned<ObjectApprover>& frameworksApprover) const
+    const Owned<ObjectApprovers>& approvers) const
 {
   mesos::master::Response::GetFrameworks getFrameworks;
   foreachvalue (const Framework* framework,
                 master->frameworks.registered) {
     // Skip unauthorized frameworks.
-    if (!approveViewFrameworkInfo(frameworksApprover, framework->info)) {
+    if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
       continue;
     }
 
@@ -1750,7 +1674,7 @@ mesos::master::Response::GetFrameworks 
Master::Http::_getFrameworks(
   foreachvalue (const Owned<Framework>& framework,
                 master->frameworks.completed) {
     // Skip unauthorized frameworks.
-    if (!approveViewFrameworkInfo(frameworksApprover, framework->info)) {
+    if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
       continue;
     }
 
@@ -1768,53 +1692,32 @@ Future<Response> Master::Http::getExecutors(
 {
   CHECK_EQ(mesos::master::Call::GET_EXECUTORS, call.type());
 
-  // Retrieve `ObjectApprover`s for authorizing frameworks and executors.
-  Future<Owned<ObjectApprover>> frameworksApprover;
-  Future<Owned<ObjectApprover>> executorsApprover;
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    frameworksApprover = master->authorizer.get()->getObjectApprover(
-        subject, authorization::VIEW_FRAMEWORK);
-
-    executorsApprover = master->authorizer.get()->getObjectApprover(
-        subject, authorization::VIEW_EXECUTOR);
-  } else {
-    frameworksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover());
-    executorsApprover = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  return collect(frameworksApprover, executorsApprover)
-    .then(defer(master->self(),
-        [=](const tuple<Owned<ObjectApprover>,
-                        Owned<ObjectApprover>>& approvers)
-          -> Future<Response> {
-      // Get approver from tuple.
-      Owned<ObjectApprover> frameworksApprover;
-      Owned<ObjectApprover> executorsApprover;
-      tie(frameworksApprover, executorsApprover) = approvers;
-
-      mesos::master::Response response;
-      response.set_type(mesos::master::Response::GET_EXECUTORS);
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {VIEW_FRAMEWORK, VIEW_EXECUTOR})
+    .then(defer(
+        master->self(),
+        [=](const Owned<ObjectApprovers>& approvers) -> Response {
+          mesos::master::Response response;
+          response.set_type(mesos::master::Response::GET_EXECUTORS);
 
-      *response.mutable_get_executors() =
-          _getExecutors(frameworksApprover, executorsApprover);
+          *response.mutable_get_executors() = _getExecutors(approvers);
 
-      return OK(serialize(contentType, evolve(response)),
-                stringify(contentType));
-    }));
+          return OK(
+              serialize(contentType, evolve(response)), 
stringify(contentType));
+        }));
 }
 
 
 mesos::master::Response::GetExecutors Master::Http::_getExecutors(
-      const Owned<ObjectApprover>& frameworksApprover,
-      const Owned<ObjectApprover>& executorsApprover) const
+      const Owned<ObjectApprovers>& approvers) const
 {
   // Construct framework list with both active and completed frameworks.
   vector<const Framework*> frameworks;
   foreachvalue (Framework* framework, master->frameworks.registered) {
     // Skip unauthorized frameworks.
-    if (!approveViewFrameworkInfo(frameworksApprover, framework->info)) {
+    if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
       continue;
     }
 
@@ -1824,7 +1727,7 @@ mesos::master::Response::GetExecutors 
Master::Http::_getExecutors(
   foreachvalue (const Owned<Framework>& framework,
                 master->frameworks.completed) {
     // Skip unauthorized frameworks.
-    if (!approveViewFrameworkInfo(frameworksApprover, framework->info)) {
+    if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
       continue;
     }
 
@@ -1839,9 +1742,8 @@ mesos::master::Response::GetExecutors 
Master::Http::_getExecutors(
                  framework->executors) {
       foreachvalue (const ExecutorInfo& executorInfo, executorsMap) {
         // Skip unauthorized executors.
-        if (!approveViewExecutorInfo(executorsApprover,
-                                     executorInfo,
-                                     framework->info)) {
+        if (!approvers->approved<VIEW_EXECUTOR>(
+                executorInfo, framework->info)) {
           continue;
         }
 
@@ -1865,72 +1767,26 @@ Future<Response> Master::Http::getState(
 {
   CHECK_EQ(mesos::master::Call::GET_STATE, call.type());
 
-  // Retrieve Approvers for authorizing frameworks and tasks.
-  Future<Owned<ObjectApprover>> frameworksApprover;
-  Future<Owned<ObjectApprover>> tasksApprover;
-  Future<Owned<ObjectApprover>> executorsApprover;
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    frameworksApprover = master->authorizer.get()->getObjectApprover(
-        subject, authorization::VIEW_FRAMEWORK);
-
-    tasksApprover = master->authorizer.get()->getObjectApprover(
-        subject, authorization::VIEW_TASK);
-
-    executorsApprover = master->authorizer.get()->getObjectApprover(
-        subject, authorization::VIEW_EXECUTOR);
-  } else {
-    frameworksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover());
-    tasksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover());
-    executorsApprover = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  Future<Owned<AuthorizationAcceptor>> rolesAcceptor =
-    AuthorizationAcceptor::create(
-        principal,
-        master->authorizer,
-        authorization::VIEW_ROLE);
-
-  return collect(
-      frameworksApprover, tasksApprover, executorsApprover, rolesAcceptor)
-    .then(defer(master->self(),
-        [=](const tuple<Owned<ObjectApprover>,
-                        Owned<ObjectApprover>,
-                        Owned<ObjectApprover>,
-                        Owned<AuthorizationAcceptor>>& approvers)
-            -> Future<Response> {
-          // Get approver from tuple.
-          Owned<ObjectApprover> frameworksApprover;
-          Owned<ObjectApprover> tasksApprover;
-          Owned<ObjectApprover> executorsApprover;
-          Owned<AuthorizationAcceptor> rolesAcceptor;
-          tie(frameworksApprover,
-              tasksApprover,
-              executorsApprover,
-              rolesAcceptor) = approvers;
-
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {VIEW_FRAMEWORK, VIEW_TASK, VIEW_EXECUTOR, VIEW_ROLE})
+    .then(defer(
+        master->self(),
+        [=](const Owned<ObjectApprovers>& approvers) -> Response {
           mesos::master::Response response;
           response.set_type(mesos::master::Response::GET_STATE);
 
-          *response.mutable_get_state() =
-              _getState(
-                  frameworksApprover,
-                  tasksApprover,
-                  executorsApprover,
-                  rolesAcceptor);
+          *response.mutable_get_state() = _getState(approvers);
 
           return OK(
               serialize(contentType, evolve(response)), 
stringify(contentType));
-    }));
+        }));
 }
 
 
 mesos::master::Response::GetState Master::Http::_getState(
-    const Owned<ObjectApprover>& frameworksApprover,
-    const Owned<ObjectApprover>& tasksApprover,
-    const Owned<ObjectApprover>& executorsApprover,
-    const Owned<AuthorizationAcceptor>& rolesAcceptor) const
+    const Owned<ObjectApprovers>& approvers) const
 {
   // NOTE: This function must be blocking instead of returning a
   // `Future`. This is because `subscribe()` needs to atomically
@@ -1939,17 +1795,10 @@ mesos::master::Response::GetState 
Master::Http::_getState(
 
   mesos::master::Response::GetState getState;
 
-  *getState.mutable_get_tasks() =
-      _getTasks(frameworksApprover, tasksApprover);
-
-  *getState.mutable_get_executors() =
-      _getExecutors(frameworksApprover, executorsApprover);
-
-  *getState.mutable_get_frameworks() =
-      _getFrameworks(frameworksApprover);
-
-  *getState.mutable_get_agents() =
-      _getAgents(rolesAcceptor);
+  *getState.mutable_get_tasks() = _getTasks(approvers);
+  *getState.mutable_get_executors() = _getExecutors(approvers);
+  *getState.mutable_get_frameworks() = _getFrameworks(approvers);
+  *getState.mutable_get_agents() = _getAgents(approvers);
 
   return getState;
 }
@@ -2207,32 +2056,18 @@ Future<Response> Master::Http::setLoggingLevel(
   Duration duration =
     Nanoseconds(call.set_logging_level().duration().nanoseconds());
 
-  Future<Owned<ObjectApprover>> approver;
-
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    approver = master->authorizer.get()->getObjectApprover(
-        subject, authorization::SET_LOG_LEVEL);
-  } else {
-    approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  return approver.then([level, duration](const Owned<ObjectApprover>& approver)
-      -> Future<Response> {
-    Try<bool> approved = approver->approved((ObjectApprover::Object()));
-
-    if (approved.isError()) {
-      return InternalServerError("Authorization error: " + approved.error());
-    } else if (!approved.get()) {
-      return Forbidden();
-    }
+  return ObjectApprovers::create(master->authorizer, principal, 
{SET_LOG_LEVEL})
+    .then([level, duration](const Owned<ObjectApprovers>& approvers)
+        -> Future<Response> {
+       if (!approvers->approved<SET_LOG_LEVEL>()) {
+        return Forbidden();
+      }
 
-    return dispatch(process::logging(), &Logging::set_level, level, duration)
+      return dispatch(process::logging(), &Logging::set_level, level, duration)
         .then([]() -> Response {
           return OK();
         });
-  });
+    });
 }
 
 
@@ -2538,63 +2373,52 @@ Future<Response> Master::Http::slaves(
     return redirect(request);
   }
 
-  Future<Owned<AuthorizationAcceptor>> authorizeRole =
-    AuthorizationAcceptor::create(
-        principal, master->authorizer, authorization::VIEW_ROLE);
-  Future<IDAcceptor<SlaveID>> selectSlaveId =
-    IDAcceptor<SlaveID>(request.url.query.get("slave_id"));
-
-  Master* master = this->master;
+  Option<string> slaveId = request.url.query.get("slave_id");
   Option<string> jsonp = request.url.query.get("jsonp");
 
-  return collect(authorizeRole, selectSlaveId)
-    .then(defer(master->self(),
-        [master, jsonp](const tuple<Owned<AuthorizationAcceptor>,
-                                    IDAcceptor<SlaveID>>& acceptors)
-          -> Future<Response> {
-      Owned<AuthorizationAcceptor> authorizeRole;
-      IDAcceptor<SlaveID> selectSlaveId;
-      tie(authorizeRole, selectSlaveId) = acceptors;
+  return ObjectApprovers::create(master->authorizer, principal, {VIEW_ROLE})
+    .then(defer(
+        master->self(),
+        [this, slaveId, jsonp](const Owned<ObjectApprovers>& approvers)
+            -> Response {
+          IDAcceptor<SlaveID> selectSlaveId(slaveId);
 
-      return OK(
-          jsonify(SlavesWriter(master->slaves, authorizeRole, selectSlaveId)),
-          jsonp);
-  }));
+          return OK(
+              jsonify(SlavesWriter(master->slaves, approvers, selectSlaveId)),
+              jsonp);
+        }));
 }
 
 
-Future<process::http::Response> Master::Http::getAgents(
+Future<Response> Master::Http::getAgents(
     const mesos::master::Call& call,
     const Option<Principal>& principal,
     ContentType contentType) const
 {
   CHECK_EQ(mesos::master::Call::GET_AGENTS, call.type());
 
-  return AuthorizationAcceptor::create(
-      principal,
-      master->authorizer,
-      authorization::VIEW_ROLE)
-    .then(defer(master->self(),
-        [=](const Owned<AuthorizationAcceptor>& rolesAcceptor)
-            -> Future<process::http::Response> {
+  return ObjectApprovers::create(master->authorizer, principal, {VIEW_ROLE})
+    .then(defer(
+        master->self(),
+        [=](const Owned<ObjectApprovers>& approvers) -> Response {
           mesos::master::Response response;
           response.set_type(mesos::master::Response::GET_AGENTS);
-          *response.mutable_get_agents() = _getAgents(rolesAcceptor);
+          *response.mutable_get_agents() = _getAgents(approvers);
 
-          return OK(serialize(contentType, evolve(response)),
-                    stringify(contentType));
+          return OK(
+              serialize(contentType, evolve(response)), 
stringify(contentType));
     }));
 }
 
 
 mesos::master::Response::GetAgents Master::Http::_getAgents(
-    const Owned<AuthorizationAcceptor>& rolesAcceptor) const
+    const Owned<ObjectApprovers>& approvers) const
 {
   mesos::master::Response::GetAgents getAgents;
   foreachvalue (const Slave* slave, master->slaves.registered) {
     mesos::master::Response::GetAgents::Agent* agent = getAgents.add_agents();
-    *agent = protobuf::master::event::createAgentResponse(
-        *slave, rolesAcceptor);
+    *agent =
+        protobuf::master::event::createAgentResponse(*slave, approvers);
   }
 
   foreachvalue (const SlaveInfo& slaveInfo, master->slaves.recovered) {
@@ -2602,7 +2426,7 @@ mesos::master::Response::GetAgents 
Master::Http::_getAgents(
     agent->CopyFrom(slaveInfo);
     agent->clear_resources();
     foreach (const Resource& resource, slaveInfo.resources()) {
-      if (authorizeResource(resource, rolesAcceptor)) {
+      if (approvers->approved<VIEW_ROLE>(resource)) {
         agent->add_resources()->CopyFrom(resource);
       }
     }
@@ -2855,195 +2679,150 @@ Future<Response> Master::Http::state(
     return redirect(request);
   }
 
-  Future<Owned<AuthorizationAcceptor>> authorizeRole =
-    AuthorizationAcceptor::create(
-        principal, master->authorizer, authorization::VIEW_ROLE);
-  Future<Owned<AuthorizationAcceptor>> authorizeFrameworkInfo =
-    AuthorizationAcceptor::create(
-        principal, master->authorizer, authorization::VIEW_FRAMEWORK);
-  Future<Owned<AuthorizationAcceptor>> authorizeTask =
-    AuthorizationAcceptor::create(
-        principal, master->authorizer, authorization::VIEW_TASK);
-  Future<Owned<AuthorizationAcceptor>> authorizeExecutorInfo =
-    AuthorizationAcceptor::create(
-        principal, master->authorizer, authorization::VIEW_EXECUTOR);
-  Future<Owned<AuthorizationAcceptor>> authorizeFlags =
-    AuthorizationAcceptor::create(
-        principal, master->authorizer, authorization::VIEW_FLAGS);
-
-  return collect(
-      authorizeRole,
-      authorizeFrameworkInfo,
-      authorizeTask,
-      authorizeExecutorInfo,
-      authorizeFlags)
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {VIEW_ROLE, VIEW_FRAMEWORK, VIEW_TASK, VIEW_EXECUTOR, VIEW_FLAGS})
     .then(defer(
         master->self(),
-        [this, request](const tuple<Owned<AuthorizationAcceptor>,
-                                    Owned<AuthorizationAcceptor>,
-                                    Owned<AuthorizationAcceptor>,
-                                    Owned<AuthorizationAcceptor>,
-                                    Owned<AuthorizationAcceptor>>& acceptors)
-          -> Response {
-      // This lambda is consumed before the outer lambda
-      // returns, hence capture by reference is fine here.
-      auto state = [this, &acceptors](JSON::ObjectWriter* writer) {
-        Owned<AuthorizationAcceptor> authorizeRole;
-        Owned<AuthorizationAcceptor> authorizeFrameworkInfo;
-        Owned<AuthorizationAcceptor> authorizeTask;
-        Owned<AuthorizationAcceptor> authorizeExecutorInfo;
-        Owned<AuthorizationAcceptor> authorizeFlags;
-        tie(authorizeRole,
-            authorizeFrameworkInfo,
-            authorizeTask,
-            authorizeExecutorInfo,
-            authorizeFlags) = acceptors;
-
-        writer->field("version", MESOS_VERSION);
-
-        if (build::GIT_SHA.isSome()) {
-          writer->field("git_sha", build::GIT_SHA.get());
-        }
-
-        if (build::GIT_BRANCH.isSome()) {
-          writer->field("git_branch", build::GIT_BRANCH.get());
-        }
-
-        if (build::GIT_TAG.isSome()) {
-          writer->field("git_tag", build::GIT_TAG.get());
-        }
-
-        writer->field("build_date", build::DATE);
-        writer->field("build_time", build::TIME);
-        writer->field("build_user", build::USER);
-        writer->field("start_time", master->startTime.secs());
-
-        if (master->electedTime.isSome()) {
-          writer->field("elected_time", master->electedTime->secs());
-        }
-
-        writer->field("id", master->info().id());
-        writer->field("pid", string(master->self()));
-        writer->field("hostname", master->info().hostname());
-        writer->field("capabilities", master->info().capabilities());
-        writer->field("activated_slaves", master->_slaves_active());
-        writer->field("deactivated_slaves", master->_slaves_inactive());
-        writer->field("unreachable_slaves", master->_slaves_unreachable());
-
-        if (master->info().has_domain()) {
-          writer->field("domain", master->info().domain());
-        }
-
-        // TODO(haosdent): Deprecated this in favor of `leader_info` below.
-        if (master->leader.isSome()) {
-          writer->field("leader", master->leader->pid());
-        }
+        [this, request](const Owned<ObjectApprovers>& approvers) -> Response {
+          // This lambda is consumed before the outer lambda
+          // returns, hence capture by reference is fine here.
+          auto state = [this, &approvers](JSON::ObjectWriter* writer) {
+            writer->field("version", MESOS_VERSION);
+
+            if (build::GIT_SHA.isSome()) {
+              writer->field("git_sha", build::GIT_SHA.get());
+            }
 
-        if (master->leader.isSome()) {
-          writer->field("leader_info", [this](JSON::ObjectWriter* writer) {
-            json(writer, master->leader.get());
-          });
-        }
+            if (build::GIT_BRANCH.isSome()) {
+              writer->field("git_branch", build::GIT_BRANCH.get());
+            }
 
-        if (authorizeFlags->accept()) {
-          if (master->flags.cluster.isSome()) {
-            writer->field("cluster", master->flags.cluster.get());
-          }
+            if (build::GIT_TAG.isSome()) {
+              writer->field("git_tag", build::GIT_TAG.get());
+            }
 
-          if (master->flags.log_dir.isSome()) {
-            writer->field("log_dir", master->flags.log_dir.get());
-          }
+            writer->field("build_date", build::DATE);
+            writer->field("build_time", build::TIME);
+            writer->field("build_user", build::USER);
+            writer->field("start_time", master->startTime.secs());
 
-          if (master->flags.external_log_file.isSome()) {
-            writer->field("external_log_file",
-                          master->flags.external_log_file.get());
-          }
+            if (master->electedTime.isSome()) {
+              writer->field("elected_time", master->electedTime->secs());
+            }
 
-          writer->field("flags", [this](JSON::ObjectWriter* writer) {
-              foreachvalue (const flags::Flag& flag, master->flags) {
-                Option<string> value = flag.stringify(master->flags);
-                if (value.isSome()) {
-                  writer->field(flag.effective_name().value, value.get());
-                }
-              }
-            });
-        }
+            writer->field("id", master->info().id());
+            writer->field("pid", string(master->self()));
+            writer->field("hostname", master->info().hostname());
+            writer->field("capabilities", master->info().capabilities());
+            writer->field("activated_slaves", master->_slaves_active());
+            writer->field("deactivated_slaves", master->_slaves_inactive());
+            writer->field("unreachable_slaves", master->_slaves_unreachable());
 
-        // Model all of the registered slaves.
-        writer->field("slaves",
-          [this, &authorizeRole](JSON::ArrayWriter* writer) {
-            foreachvalue (Slave* slave, master->slaves.registered) {
-              writer->element(SlaveWriter(*slave, authorizeRole));
+            if (master->info().has_domain()) {
+              writer->field("domain", master->info().domain());
             }
-          });
 
-        // Model all of the recovered slaves.
-        writer->field("recovered_slaves", [this](JSON::ArrayWriter* writer) {
-          foreachvalue (const SlaveInfo& slaveInfo, master->slaves.recovered) {
-            writer->element([&slaveInfo](JSON::ObjectWriter* writer) {
-              json(writer, slaveInfo);
-            });
-          }
-        });
+            // TODO(haosdent): Deprecated this in favor of `leader_info` below.
+            if (master->leader.isSome()) {
+              writer->field("leader", master->leader->pid());
+            }
 
-        // Model all of the frameworks.
-        writer->field(
-            "frameworks",
-            [this,
-             &authorizeFrameworkInfo,
-             &authorizeTask,
-             &authorizeExecutorInfo](JSON::ArrayWriter* writer) {
-          foreachvalue (
-              Framework* framework,
-              master->frameworks.registered) {
-            // Skip unauthorized frameworks.
-            if (!authorizeFrameworkInfo->accept(framework->info)) {
-              continue;
+            if (master->leader.isSome()) {
+              writer->field("leader_info", [this](JSON::ObjectWriter* writer) {
+                json(writer, master->leader.get());
+              });
             }
 
-            auto frameworkWriter = FullFrameworkWriter(
-                authorizeTask,
-                authorizeExecutorInfo,
-                framework);
+            if (approvers->approved<VIEW_FLAGS>()) {
+              if (master->flags.cluster.isSome()) {
+                writer->field("cluster", master->flags.cluster.get());
+              }
 
-            writer->element(frameworkWriter);
-          }
-        });
+              if (master->flags.log_dir.isSome()) {
+                writer->field("log_dir", master->flags.log_dir.get());
+              }
 
-        // Model all of the completed frameworks.
-        writer->field(
-            "completed_frameworks",
-            [this,
-             &authorizeFrameworkInfo,
-             &authorizeTask,
-             &authorizeExecutorInfo](JSON::ArrayWriter* writer) {
-          foreachvalue (const Owned<Framework>& framework,
-                        master->frameworks.completed) {
-            // Skip unauthorized frameworks.
-            if (!authorizeFrameworkInfo->accept(framework->info)) {
-              continue;
-            }
+              if (master->flags.external_log_file.isSome()) {
+                writer->field("external_log_file",
+                              master->flags.external_log_file.get());
+              }
 
-            auto frameworkWriter = FullFrameworkWriter(
-                authorizeTask,
-                authorizeExecutorInfo,
-                framework.get());
+              writer->field("flags", [this](JSON::ObjectWriter* writer) {
+                  foreachvalue (const flags::Flag& flag, master->flags) {
+                    Option<string> value = flag.stringify(master->flags);
+                    if (value.isSome()) {
+                      writer->field(flag.effective_name().value, value.get());
+                    }
+                  }
+                });
+            }
 
-            writer->element(frameworkWriter);
-          }
-        });
+            // Model all of the registered slaves.
+            writer->field(
+                "slaves",
+                [this, &approvers](JSON::ArrayWriter* writer) {
+                  foreachvalue (Slave* slave, master->slaves.registered) {
+                    writer->element(SlaveWriter(*slave, approvers));
+                  }
+                });
+
+            // Model all of the recovered slaves.
+            writer->field(
+                "recovered_slaves",
+                [this](JSON::ArrayWriter* writer) {
+                  foreachvalue (
+                      const SlaveInfo& slaveInfo, master->slaves.recovered) {
+                    writer->element([&slaveInfo](JSON::ObjectWriter* writer) {
+                      json(writer, slaveInfo);
+                    });
+                  }
+                });
+
+            // Model all of the frameworks.
+            writer->field(
+                "frameworks",
+                [this, &approvers](JSON::ArrayWriter* writer) {
+                  foreachvalue (
+                      Framework* framework, master->frameworks.registered) {
+                    // Skip unauthorized frameworks.
+                    if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) 
{
+                      continue;
+                    }
+
+                    writer->element(FullFrameworkWriter(approvers, framework));
+                  }
+                });
+
+            // Model all of the completed frameworks.
+            writer->field(
+                "completed_frameworks",
+                [this, &approvers](JSON::ArrayWriter* writer) {
+                  foreachvalue (
+                      const Owned<Framework>& framework,
+                      master->frameworks.completed) {
+                    // Skip unauthorized frameworks.
+                    if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) 
{
+                      continue;
+                    }
+
+                    writer->element(
+                        FullFrameworkWriter(approvers, framework.get()));
+                  }
+                });
 
-        // Orphan tasks are no longer possible. We emit an empty array
-        // for the sake of backward compatibility.
-        writer->field("orphan_tasks", [](JSON::ArrayWriter*) {});
+            // Orphan tasks are no longer possible. We emit an empty array
+            // for the sake of backward compatibility.
+            writer->field("orphan_tasks", [](JSON::ArrayWriter*) {});
 
-        // Unregistered frameworks are no longer possible. We emit an
-        // empty array for the sake of backward compatibility.
-        writer->field("unregistered_frameworks", [](JSON::ArrayWriter*) {});
-      };
+            // Unregistered frameworks are no longer possible. We emit an
+            // empty array for the sake of backward compatibility.
+            writer->field("unregistered_frameworks", [](JSON::ArrayWriter*) 
{});
+          };
 
-      return OK(jsonify(state), request.url.query.get("jsonp"));
-    }));
+          return OK(jsonify(state), request.url.query.get("jsonp"));
+        }));
 }
 
 
@@ -3318,156 +3097,153 @@ Future<Response> Master::Http::stateSummary(
     return redirect(request);
   }
 
-  Future<Owned<AuthorizationAcceptor>> authorizeRole =
-    AuthorizationAcceptor::create(
-        principal, master->authorizer, authorization::VIEW_ROLE);
-  Future<Owned<AuthorizationAcceptor>> authorizeFrameworkInfo =
-    AuthorizationAcceptor::create(
-        principal, master->authorizer, authorization::VIEW_FRAMEWORK);
-
-  return collect(authorizeRole, authorizeFrameworkInfo).then(defer(
-      master->self(),
-      [this, request](const tuple<Owned<AuthorizationAcceptor>,
-                                  Owned<AuthorizationAcceptor>>& acceptors)
-          -> Response {
-        auto stateSummary = [this, &acceptors](JSON::ObjectWriter* writer) {
-          Owned<AuthorizationAcceptor> authorizeRole;
-          Owned<AuthorizationAcceptor> authorizeFrameworkInfo;
-          tie(authorizeRole, authorizeFrameworkInfo) = acceptors;
-
-          writer->field("hostname", master->info().hostname());
-
-          if (master->flags.cluster.isSome()) {
-            writer->field("cluster", master->flags.cluster.get());
-          }
-
-          // We use the tasks in the 'Frameworks' struct to compute summaries
-          // for this endpoint. This is done 1) for consistency between the
-          // 'slaves' and 'frameworks' subsections below 2) because we want to
-          // provide summary information for frameworks that are currently
-          // registered 3) the frameworks keep a circular buffer of completed
-          // tasks that we can use to keep a limited view on the history of
-          // recent completed / failed tasks.
-
-          // Generate mappings from 'slave' to 'framework' and reverse.
-          SlaveFrameworkMapping slaveFrameworkMapping(
-              master->frameworks.registered);
-
-          // Generate 'TaskState' summaries for all framework and slave ids.
-          TaskStateSummaries taskStateSummaries(master->frameworks.registered);
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {VIEW_ROLE, VIEW_FRAMEWORK})
+    .then(defer(
+        master->self(),
+        [this, request](const Owned<ObjectApprovers>& approvers) -> Response {
+          auto stateSummary = [this, &approvers](JSON::ObjectWriter* writer) {
+            writer->field("hostname", master->info().hostname());
 
-          // Model all of the slaves.
-          writer->field(
-              "slaves",
-              [this,
-               &slaveFrameworkMapping,
-               &taskStateSummaries,
-               &authorizeRole](JSON::ArrayWriter* writer) {
-                foreachvalue (Slave* slave, master->slaves.registered) {
-                  writer->element(
-                      [&slave,
-                       &slaveFrameworkMapping,
-                       &taskStateSummaries,
-                       &authorizeRole](JSON::ObjectWriter* writer) {
-                        SlaveWriter slaveWriter(*slave, authorizeRole);
-                        slaveWriter(writer);
-
-                        // Add the 'TaskState' summary for this slave.
-                        const TaskStateSummary& summary =
-                            taskStateSummaries.slave(slave->id);
-
-                        // Certain per-agent status totals will always be zero
-                        // (e.g., TASK_ERROR, TASK_UNREACHABLE). We report them
-                        // here anyway, for completeness.
-                        //
-                        // TODO(neilc): Update for TASK_GONE and
-                        // TASK_GONE_BY_OPERATOR.
-                        writer->field("TASK_STAGING", summary.staging);
-                        writer->field("TASK_STARTING", summary.starting);
-                        writer->field("TASK_RUNNING", summary.running);
-                        writer->field("TASK_KILLING", summary.killing);
-                        writer->field("TASK_FINISHED", summary.finished);
-                        writer->field("TASK_KILLED", summary.killed);
-                        writer->field("TASK_FAILED", summary.failed);
-                        writer->field("TASK_LOST", summary.lost);
-                        writer->field("TASK_ERROR", summary.error);
-                        writer->field("TASK_UNREACHABLE", summary.unreachable);
-
-                        // Add the ids of all the frameworks running on this
-                        // slave.
-                        const hashset<FrameworkID>& frameworks =
-                            slaveFrameworkMapping.frameworks(slave->id);
-
-                        writer->field(
-                            "framework_ids",
-                            [&frameworks](JSON::ArrayWriter* writer) {
-                              foreach (
-                                  const FrameworkID& frameworkId,
-                                  frameworks) {
-                                writer->element(frameworkId.value());
-                              }
-                            });
-                      });
-                }
-              });
+            if (master->flags.cluster.isSome()) {
+              writer->field("cluster", master->flags.cluster.get());
+            }
 
-          // Model all of the frameworks.
-          writer->field(
-              "frameworks",
-              [this,
-               &slaveFrameworkMapping,
-               &taskStateSummaries,
-               &authorizeFrameworkInfo](JSON::ArrayWriter* writer) {
-                foreachpair (const FrameworkID& frameworkId,
-                             Framework* framework,
-                             master->frameworks.registered) {
-                  // Skip unauthorized frameworks.
-                  if (!authorizeFrameworkInfo->accept(framework->info)) {
-                    continue;
+            // We use the tasks in the 'Frameworks' struct to compute summaries
+            // for this endpoint. This is done 1) for consistency between the
+            // 'slaves' and 'frameworks' subsections below 2) because we want 
to
+            // provide summary information for frameworks that are currently
+            // registered 3) the frameworks keep a circular buffer of completed
+            // tasks that we can use to keep a limited view on the history of
+            // recent completed / failed tasks.
+
+            // Generate mappings from 'slave' to 'framework' and reverse.
+            SlaveFrameworkMapping slaveFrameworkMapping(
+                master->frameworks.registered);
+
+            // Generate 'TaskState' summaries for all framework and slave ids.
+            TaskStateSummaries taskStateSummaries(
+                master->frameworks.registered);
+
+            // Model all of the slaves.
+            writer->field(
+                "slaves",
+                [this,
+                 &slaveFrameworkMapping,
+                 &taskStateSummaries,
+                 &approvers](JSON::ArrayWriter* writer) {
+                  foreachvalue (Slave* slave, master->slaves.registered) {
+                    writer->element(
+                        [&slave,
+                         &slaveFrameworkMapping,
+                         &taskStateSummaries,
+                         &approvers](JSON::ObjectWriter* writer) {
+                          SlaveWriter slaveWriter(*slave, approvers);
+                          slaveWriter(writer);
+
+                          // Add the 'TaskState' summary for this slave.
+                          const TaskStateSummary& summary =
+                              taskStateSummaries.slave(slave->id);
+
+                          // Certain per-agent status totals will always be 
zero
+                          // (e.g., TASK_ERROR, TASK_UNREACHABLE). We report
+                          // them here anyway, for completeness.
+                          //
+                          // TODO(neilc): Update for TASK_GONE and
+                          // TASK_GONE_BY_OPERATOR.
+                          writer->field("TASK_STAGING", summary.staging);
+                          writer->field("TASK_STARTING", summary.starting);
+                          writer->field("TASK_RUNNING", summary.running);
+                          writer->field("TASK_KILLING", summary.killing);
+                          writer->field("TASK_FINISHED", summary.finished);
+                          writer->field("TASK_KILLED", summary.killed);
+                          writer->field("TASK_FAILED", summary.failed);
+                          writer->field("TASK_LOST", summary.lost);
+                          writer->field("TASK_ERROR", summary.error);
+                          writer->field(
+                              "TASK_UNREACHABLE",
+                              summary.unreachable);
+
+                          // Add the ids of all the frameworks running on this
+                          // slave.
+                          const hashset<FrameworkID>& frameworks =
+                              slaveFrameworkMapping.frameworks(slave->id);
+
+                          writer->field(
+                              "framework_ids",
+                              [&frameworks](JSON::ArrayWriter* writer) {
+                                foreach (
+                                    const FrameworkID& frameworkId,
+                                    frameworks) {
+                                  writer->element(frameworkId.value());
+                                }
+                              });
+                        });
                   }
+                });
+
+            // Model all of the frameworks.
+            writer->field(
+                "frameworks",
+                [this,
+                 &slaveFrameworkMapping,
+                 &taskStateSummaries,
+                 &approvers](JSON::ArrayWriter* writer) {
+                  foreachpair (const FrameworkID& frameworkId,
+                               Framework* framework,
+                               master->frameworks.registered) {
+                    // Skip unauthorized frameworks.
+                    if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) 
{
+                      continue;
+                    }
+
+                    writer->element(
+                        [&frameworkId,
+                         &framework,
+                         &slaveFrameworkMapping,
+                         &taskStateSummaries](JSON::ObjectWriter* writer) {
+                          json(writer, Summary<Framework>(*framework));
+
+                          // Add the 'TaskState' summary for this framework.
+                          const TaskStateSummary& summary =
+                              taskStateSummaries.framework(frameworkId);
+
+                          // TODO(neilc): Update for TASK_GONE and
+                          // TASK_GONE_BY_OPERATOR.
+                          writer->field("TASK_STAGING", summary.staging);
+                          writer->field("TASK_STARTING", summary.starting);
+                          writer->field("TASK_RUNNING", summary.running);
+                          writer->field("TASK_KILLING", summary.killing);
+                          writer->field("TASK_FINISHED", summary.finished);
+                          writer->field("TASK_KILLED", summary.killed);
+                          writer->field("TASK_FAILED", summary.failed);
+                          writer->field("TASK_LOST", summary.lost);
+                          writer->field("TASK_ERROR", summary.error);
+                          writer->field(
+                              "TASK_UNREACHABLE",
+                              summary.unreachable);
+
+                          // Add the ids of all the slaves running
+                          // this framework.
+                          const hashset<SlaveID>& slaves =
+                              slaveFrameworkMapping.slaves(frameworkId);
+
+                          writer->field(
+                              "slave_ids",
+                              [&slaves](JSON::ArrayWriter* writer) {
+                                foreach (const SlaveID& slaveId, slaves) {
+                                  writer->element(slaveId.value());
+                                }
+                              });
+                        });
+                  }
+                });
+          };
 
-                  writer->element(
-                      [&frameworkId,
-                       &framework,
-                       &slaveFrameworkMapping,
-                       &taskStateSummaries](JSON::ObjectWriter* writer) {
-                        json(writer, Summary<Framework>(*framework));
-
-                        // Add the 'TaskState' summary for this framework.
-                        const TaskStateSummary& summary =
-                            taskStateSummaries.framework(frameworkId);
-
-                        // TODO(neilc): Update for TASK_GONE and
-                        // TASK_GONE_BY_OPERATOR.
-                        writer->field("TASK_STAGING", summary.staging);
-                        writer->field("TASK_STARTING", summary.starting);
-                        writer->field("TASK_RUNNING", summary.running);
-                        writer->field("TASK_KILLING", summary.killing);
-                        writer->field("TASK_FINISHED", summary.finished);
-                        writer->field("TASK_KILLED", summary.killed);
-                        writer->field("TASK_FAILED", summary.failed);
-                        writer->field("TASK_LOST", summary.lost);
-                        writer->field("TASK_ERROR", summary.error);
-                        writer->field("TASK_UNREACHABLE", summary.unreachable);
-
-                        // Add the ids of all the slaves running this 
framework.
-                        const hashset<SlaveID>& slaves =
-                            slaveFrameworkMapping.slaves(frameworkId);
-
-                        writer->field(
-                            "slave_ids",
-                            [&slaves](JSON::ArrayWriter* writer) {
-                              foreach (const SlaveID& slaveId, slaves) {
-                                writer->element(slaveId.value());
-                              }
-                            });
-                      });
-                }
-              });
-        };
-
-        return OK(jsonify(stateSummary), request.url.query.get("jsonp"));
-      }));
+          return OK(jsonify(stateSummary), request.url.query.get("jsonp"));
+        }));
 }
 
 
@@ -3540,21 +3316,9 @@ string Master::Http::ROLES_HELP()
 Future<vector<string>> Master::Http::_roles(
     const Option<Principal>& principal) const
 {
-  // Retrieve `ObjectApprover`s for authorizing roles.
-  Future<Owned<ObjectApprover>> rolesApprover;
-
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    rolesApprover = master->authorizer.get()->getObjectApprover(
-        subject, authorization::VIEW_ROLE);
-  } else {
-    rolesApprover = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  return rolesApprover
+  return ObjectApprovers::create(master->authorizer, principal, {VIEW_ROLE})
     .then(defer(master->self(),
-        [this](const Owned<ObjectApprover>& rolesApprover)
+        [this](const Owned<ObjectApprovers>& approvers)
           -> vector<string> {
       JSON::Object object;
 
@@ -3587,7 +3351,7 @@ Future<vector<string>> Master::Http::_roles(
       filteredRoleList.reserve(roleList.size());
 
       foreach (const string& role, roleList) {
-        if (approveViewRole(rolesApprover, role)) {
+        if (approvers->approved<VIEW_ROLE>(role)) {
           filteredRoleList.push_back(role);
         }
       }
@@ -4032,40 +3796,18 @@ Future<Response> Master::Http::tasks(
   Option<string> order = request.url.query.get("order");
   string _order = order.isSome() && (order.get() == "asc") ? "asc" : "des";
 
-  Future<Owned<AuthorizationAcceptor>> authorizeFrameworkInfo =
-    AuthorizationAcceptor::create(
-        principal,
-        master->authorizer,
-        authorization::VIEW_FRAMEWORK);
-  Future<Owned<AuthorizationAcceptor>> authorizeTask =
-    AuthorizationAcceptor::create(
-        principal,
-        master->authorizer,
-        authorization::VIEW_TASK);
-  Future<IDAcceptor<FrameworkID>> selectFrameworkId =
-    IDAcceptor<FrameworkID>(request.url.query.get("framework_id"));
-  Future<IDAcceptor<TaskID>> selectTaskId =
-    IDAcceptor<TaskID>(request.url.query.get("task_id"));
-
-  return collect(
-      authorizeFrameworkInfo,
-      authorizeTask,
-      selectFrameworkId,
-      selectTaskId)
+  Option<string> frameworkId = request.url.query.get("framework_id");
+  Option<string> taskId = request.url.query.get("task_id");
+
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {VIEW_FRAMEWORK, VIEW_TASK})
     .then(defer(
         master->self(),
-        [=](const tuple<Owned<AuthorizationAcceptor>,
-                        Owned<AuthorizationAcceptor>,
-                        IDAcceptor<FrameworkID>,
-                        IDAcceptor<TaskID>>& acceptors)-> Future<Response> {
-          Owned<AuthorizationAcceptor> authorizeFrameworkInfo;
-          Owned<AuthorizationAcceptor> authorizeTask;
-          IDAcceptor<FrameworkID> selectFrameworkId;
-          IDAcceptor<TaskID> selectTaskId;
-          tie(authorizeFrameworkInfo,
-              authorizeTask,
-              selectFrameworkId,
-              selectTaskId) = acceptors;
+        [=](const Owned<ObjectApprovers>& approvers) -> Response {
+          IDAcceptor<FrameworkID> selectFrameworkId(frameworkId);
+          IDAcceptor<TaskID> selectTaskId(taskId);
 
           // Construct framework list with both active and completed 
frameworks.
           vector<const Framework*> frameworks;
@@ -4073,7 +3815,7 @@ Future<Response> Master::Http::tasks(
             // Skip unauthorized frameworks or frameworks without matching
             // framework ID.
             if (!selectFrameworkId.accept(framework->id()) ||
-                !authorizeFrameworkInfo->accept(framework->info)) {
+                !approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
               continue;
             }
 
@@ -4085,7 +3827,7 @@ Future<Response> Master::Http::tasks(
             // Skip unauthorized frameworks or frameworks without matching
             // framework ID.
             if (!selectFrameworkId.accept(framework->id()) ||
-                !authorizeFrameworkInfo->accept(framework->info)) {
+                !approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
              continue;
             }
 
@@ -4100,7 +3842,7 @@ Future<Response> Master::Http::tasks(
               CHECK_NOTNULL(task);
               // Skip unauthorized tasks or tasks without matching task ID.
               if (!selectTaskId.accept(task->task_id()) ||
-                  !authorizeTask->accept(*task, framework->info)) {
+                  !approvers->approved<VIEW_TASK>(*task, framework->info)) {
                 continue;
               }
 
@@ -4112,7 +3854,7 @@ Future<Response> Master::Http::tasks(
                 framework->unreachableTasks) {
               // Skip unauthorized tasks or tasks without matching task ID.
               if (!selectTaskId.accept(task->task_id()) ||
-                  !authorizeTask->accept(*task, framework->info)) {
+                  !approvers->approved<VIEW_TASK>(*task, framework->info)) {
                 continue;
               }
 
@@ -4122,7 +3864,7 @@ Future<Response> Master::Http::tasks(
             foreach (const Owned<Task>& task, framework->completedTasks) {
               // Skip unauthorized tasks or tasks without matching task ID.
               if (!selectTaskId.accept(task->task_id()) ||
-                  !authorizeTask->accept(*task, framework->info)) {
+                  !approvers->approved<VIEW_TASK>(*task, framework->info)) {
                 continue;
               }
 
@@ -4141,14 +3883,15 @@ Future<Response> Master::Http::tasks(
 
           auto tasksWriter =
             [&tasks, limit, offset](JSON::ObjectWriter* writer) {
-            writer->field("tasks",
-                          [&tasks, limit, offset](JSON::ArrayWriter* writer) {
-              // Collect 'limit' number of tasks starting from 'offset'.
-              size_t end = std::min(offset + limit, tasks.size());
-              for (size_t i = offset; i < end; i++) {
-                writer->element(*tasks[i]);
-              }
-            });
+              writer->field(
+                  "tasks",
+                  [&tasks, limit, offset](JSON::ArrayWriter* writer) {
+                    // Collect 'limit' number of tasks starting from 'offset'.
+                    size_t end = std::min(offset + limit, tasks.size());
+                    for (size_t i = offset; i < end; i++) {
+                      writer->element(*tasks[i]);
+                    }
+                  });
           };
 
           return OK(jsonify(tasksWriter), request.url.query.get("jsonp"));
@@ -4163,54 +3906,32 @@ Future<Response> Master::Http::getTasks(
 {
   CHECK_EQ(mesos::master::Call::GET_TASKS, call.type());
 
-  // Retrieve Approvers for authorizing frameworks and tasks.
-  Future<Owned<ObjectApprover>> frameworksApprover;
-  Future<Owned<ObjectApprover>> tasksApprover;
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    frameworksApprover = master->authorizer.get()->getObjectApprover(
-        subject, authorization::VIEW_FRAMEWORK);
-
-    tasksApprover = master->authorizer.get()->getObjectApprover(
-        subject, authorization::VIEW_TASK);
-  } else {
-    frameworksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover());
-    tasksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  return collect(frameworksApprover, tasksApprover)
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {VIEW_FRAMEWORK, VIEW_TASK})
     .then(defer(
         master->self(),
-        [=](const tuple<Owned<ObjectApprover>,
-                        Owned<ObjectApprover>>& approvers)
-        -> Future<Response> {
-      // Get approver from tuple.
-      Owned<ObjectApprover> frameworksApprover;
-      Owned<ObjectApprover> tasksApprover;
-      tie(frameworksApprover, tasksApprover) = approvers;
-
-      mesos::master::Response response;
-      response.set_type(mesos::master::Response::GET_TASKS);
+        [=](const Owned<ObjectApprovers>& approvers) -> Response {
+          mesos::master::Response response;
+          response.set_type(mesos::master::Response::GET_TASKS);
 
-      *response.mutable_get_tasks() =
-        _getTasks(frameworksApprover, tasksApprover);
+          *response.mutable_get_tasks() = _getTasks(approvers);
 
-      return OK(serialize(contentType, evolve(response)),
-                stringify(contentType));
+          return OK(
+              serialize(contentType, evolve(response)), 
stringify(contentType));
   }));
 }
 
 
 mesos::master::Response::GetTasks Master::Http::_getTasks(
-    const Owned<ObjectApprover>& frameworksApprover,
-    const Owned<ObjectApprover>& tasksApprover) const
+    const Owned<ObjectApprovers>& approvers) const
 {
   // Construct framework list with both active and completed frameworks.
   vector<const Framework*> frameworks;
   foreachvalue (Framework* framework, master->frameworks.registered) {
     // Skip unauthorized frameworks.
-    if (!approveViewFrameworkInfo(frameworksApprover, framework->info)) {
+    if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
       continue;
     }
 
@@ -4220,7 +3941,7 @@ mesos::master::Response::GetTasks Master::Http::_getTasks(
   foreachvalue (const Owned<Framework>& framework,
                 master->frameworks.completed) {
     // Skip unauthorized frameworks.
-    if (!approveViewFrameworkInfo(frameworksApprover, framework->info)) {
+    if (!approvers->approved<VIEW_FRAMEWORK>(framework->info)) {
       continue;
     }
 
@@ -4234,7 +3955,7 @@ mesos::master::Response::GetTasks Master::Http::_getTasks(
     // Pending tasks.
     foreachvalue (const TaskInfo& taskInfo, framework->pendingTasks) {
       // Skip unauthorized tasks.
-      if (!approveViewTaskInfo(tasksApprover, taskInfo, framework->info)) {
+      if (!approvers->approved<VIEW_TASK>(taskInfo, framework->info)) {
         continue;
       }
 
@@ -4246,7 +3967,7 @@ mesos::master::Response::GetTasks Master::Http::_getTasks(
     foreachvalue (Task* task, framework->tasks) {
       CHECK_NOTNULL(task);
       // Skip unauthorized tasks.
-      if (!approveViewTask(tasksApprover, *task, framework->info)) {
+      if (!approvers->approved<VIEW_TASK>(*task, framework->info)) {
         continue;
       }
 
@@ -4256,7 +3977,7 @@ mesos::master::Response::GetTasks Master::Http::_getTasks(
     // Unreachable tasks.
     foreachvalue (const Owned<Task>& task, framework->unreachableTasks) {
       // Skip unauthorized tasks.
-      if (!approveViewTask(tasksApprover, *task, framework->info)) {
+      if (!approvers->approved<VIEW_TASK>(*task, framework->info)) {
         continue;
       }
 
@@ -4266,7 +3987,7 @@ mesos::master::Response::GetTasks Master::Http::_getTasks(
     // Completed tasks.
     foreach (const Owned<Task>& task, framework->completedTasks) {
       // Skip unauthorized tasks.
-      if (!approveViewTask(tasksApprover, *task, framework->info)) {
+      if (!approvers->approved<VIEW_TASK>(*task, framework->info)) {
         continue;
       }
 
@@ -4327,25 +4048,17 @@ Future<Response> Master::Http::maintenanceSchedule(
 
   // JSON-ify and return the current maintenance schedule.
   if (request.method == "GET") {
-    Future<Owned<ObjectApprover>> approver;
-
-    if (master->authorizer.isSome()) {
-      Option<authorization::Subject> subject = createSubject(principal);
-
-      approver = master->authorizer.get()->getObjectApprover(
-          subject, authorization::GET_MAINTENANCE_SCHEDULE);
-    } else {
-      approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
-    }
-
     Option<string> jsonp = request.url.query.get("jsonp");
 
-    return approver.then(defer(
+    return ObjectApprovers::create(
+        master->authorizer,
+        principal,
+        {GET_MAINTENANCE_SCHEDULE})
+      .then(defer(
         master->self(),
-        [this, jsonp](
-            const Owned<ObjectApprover>& approver) -> Future<Response> {
+        [this, jsonp](const Owned<ObjectApprovers>& approvers) -> Response {
           const mesos::maintenance::Schedule schedule =
-            _getMaintenanceSchedule(approver);
+            _getMaintenanceSchedule(approvers);
           return OK(JSON::protobuf(schedule), jsonp);
         }));
   }
@@ -4369,7 +4082,7 @@ Future<Response> Master::Http::maintenanceSchedule(
 
 
 mesos::maintenance::Schedule Master::Http::_getMaintenanceSchedule(
-    const Owned<ObjectApprover>& approver) const
+    const Owned<ObjectApprovers>& approvers) const
 {
   // TODO(josephw): Return more than one schedule.
   if (master->maintenance.schedules.empty()) {
@@ -4383,17 +4096,7 @@ mesos::maintenance::Schedule 
Master::Http::_getMaintenanceSchedule(
     mesos::maintenance::Window window_;
 
     foreach (const MachineID& machine_id, window.machine_ids()) {
-      Try<bool> approved =
-        approver->approved(ObjectApprover::Object(machine_id));
-
-      if (approved.isError()) {
-        LOG(WARNING) << "Error during MachineID authorization: "
-                     << approved.error();
-        // TODO(arojas): Consider exposing these errors to the caller.
-        continue;
-      }
-
-      if (!approved.get()) {
+      if (!approvers->approved<GET_MAINTENANCE_SCHEDULE>(machine_id)) {
         continue;
       }
 
@@ -4424,35 +4127,24 @@ Future<Response> 
Master::Http::_updateMaintenanceSchedule(
     return BadRequest(isValid.error());
   }
 
-  Future<Owned<ObjectApprover>> approver;
-
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    approver = master->authorizer.get()->getObjectApprover(
-        subject, authorization::UPDATE_MAINTENANCE_SCHEDULE);
-  } else {
-    approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  return approver.then(defer(
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {UPDATE_MAINTENANCE_SCHEDULE})
+    .then(defer(
       master->self(),
-      [this, schedule](const Owned<ObjectApprover>& approver) {
-        return __updateMaintenanceSchedule(schedule, approver);
+      [this, schedule](const Owned<ObjectApprovers>& approvers) {
+        return __updateMaintenanceSchedule(schedule, approvers);
       }));
 }
 
 Future<Response> Master::Http::__updateMaintenanceSchedule(
     const mesos::maintenance::Schedule& schedule,
-    const Owned<ObjectApprover>& approver) const
+    const Owned<ObjectApprovers>& approvers) const
 {
   foreach (const mesos::maintenance::Window& window, schedule.windows()) {
     foreach (const MachineID& machine, window.machine_ids()) {
-      Try<bool> approved = approver->approved(ObjectApprover::Object(machine));
-
-      if (approved.isError()) {
-        return InternalServerError("Authorization error: " + approved.error());
-      } else if (!approved.get()) {
+      if (!approvers->approved<UPDATE_MAINTENANCE_SCHEDULE>(machine)) {
         return Forbidden();
       }
     }
@@ -4549,27 +4241,19 @@ Future<Response> Master::Http::getMaintenanceSchedule(
 {
   CHECK_EQ(mesos::master::Call::GET_MAINTENANCE_SCHEDULE, call.type());
 
-  Future<Owned<ObjectApprover>> approver;
-
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    approver = master->authorizer.get()->getObjectApprover(
-        subject, authorization::GET_MAINTENANCE_SCHEDULE);
-  } else {
-    approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  return approver.then(defer(
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {GET_MAINTENANCE_SCHEDULE})
+    .then(defer(
       master->self(),
-      [this, contentType](
-          const Owned<ObjectApprover>& approver) -> Future<Response> {
+      [this, contentType](const Owned<ObjectApprovers>& approvers) -> Response 
{
         mesos::master::Response response;
 
         response.set_type(mesos::master::Response::GET_MAINTENANCE_SCHEDULE);
 
         *response.mutable_get_maintenance_schedule()->mutable_schedule() =
-          _getMaintenanceSchedule(approver);
+          _getMaintenanceSchedule(approvers);
 
         return OK(serialize(contentType, evolve(response)),
                   stringify(contentType));
@@ -4643,28 +4327,21 @@ Future<Response> Master::Http::machineDown(
     return BadRequest(ids.error());
   }
 
-  Future<Owned<ObjectApprover>> approver;
-
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    approver = master->authorizer.get()->getObjectApprover(
-        subject, authorization::START_MAINTENANCE);
-  } else {
-    approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  return approver.then(defer(
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {START_MAINTENANCE})
+    .then(defer(
       master->self(),
-      [this, ids](const Owned<ObjectApprover>& approver) {
-        return _startMaintenance(ids.get(), approver);
+      [this, ids](const Owned<ObjectApprovers>& approvers) {
+        return _startMaintenance(ids.get(), approvers);
       }));
 }
 
 
 Future<Response> Master::Http::_startMaintenance(
     const RepeatedPtrField<MachineID>& machineIds,
-    const Owned<ObjectApprover>& approver) const
+    const Owned<ObjectApprovers>& approvers) const
 {
   // Validate every machine in the list.
   Try<Nothing> isValid = maintenance::validation::machines(machineIds);
@@ -4687,18 +4364,14 @@ Future<Response> Master::Http::_startMaintenance(
             "' is not in DRAINING mode and cannot be brought down");
     }
 
-    Try<bool> approved = approver->approved(ObjectApprover::Object(id));
-
-    if (approved.isError()) {
-      return InternalServerError("Authorization error: " + approved.error());
-    } else if (!approved.get()) {
+    if (!approvers->approved<START_MAINTENANCE>(id)) {
       return Forbidden();
     }
   }
 
   return master->registrar->apply(Owned<RegistryOperation>(
       new maintenance::StartMaintenance(machineIds)))
-    .then(defer(master->self(), [=](bool result) -> Future<Response> {
+    .then(defer(master->self(), [=](bool result) -> Response {
       // See the top comment in "master/maintenance.hpp" for why this check
       // is here, and is appropriate.
       CHECK(result);
@@ -4752,23 +4425,16 @@ Future<Response> Master::Http::startMaintenance(
   CHECK_EQ(mesos::master::Call::START_MAINTENANCE, call.type());
   CHECK(call.has_start_maintenance());
 
-  Future<Owned<ObjectApprover>> approver;
-
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    approver = master->authorizer.get()->getObjectApprover(
-        subject, authorization::START_MAINTENANCE);
-  } else {
-    approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
   RepeatedPtrField<MachineID> machineIds = call.start_maintenance().machines();
 
-  return approver.then(defer(
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {START_MAINTENANCE})
+    .then(defer(
       master->self(),
-      [this, machineIds](const Owned<ObjectApprover>& approver) {
-        return _startMaintenance(machineIds, approver);
+      [this, machineIds](const Owned<ObjectApprovers>& approvers) {
+        return _startMaintenance(machineIds, approvers);
       }));
 }
 
@@ -4824,28 +4490,21 @@ Future<Response> Master::Http::machineUp(
     return BadRequest(ids.error());
   }
 
-  Future<Owned<ObjectApprover>> approver;
-
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    approver = master->authorizer.get()->getObjectApprover(
-        subject, authorization::STOP_MAINTENANCE);
-  } else {
-    approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  return approver.then(defer(
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {STOP_MAINTENANCE})
+    .then(defer(
       master->self(),
-      [this, ids](const Owned<ObjectApprover>& approver) {
-        return _stopMaintenance(ids.get(), approver);
+      [this, ids](const Owned<ObjectApprovers>& approvers) {
+        return _stopMaintenance(ids.get(), approvers);
       }));
 }
 
 
 Future<Response> Master::Http::_stopMaintenance(
     const RepeatedPtrField<MachineID>& machineIds,
-    const Owned<ObjectApprover>& approver) const
+    const Owned<ObjectApprovers>& approvers) const
 {
   // Validate every machine in the list.
   Try<Nothing> isValid = maintenance::validation::machines(machineIds);
@@ -4867,11 +4526,7 @@ Future<Response> Master::Http::_stopMaintenance(
             "' is not in DOWN mode and cannot be brought up");
     }
 
-    Try<bool> approved = approver->approved(ObjectApprover::Object(id));
-
-    if (approved.isError()) {
-      return InternalServerError("Authorization error: " + approved.error());
-    } else if (!approved.get()) {
+    if (!approvers->approved<STOP_MAINTENANCE>(id)) {
       return Forbidden();
     }
   }
@@ -4934,22 +4589,14 @@ Future<Response> Master::Http::stopMaintenance(
 
   RepeatedPtrField<MachineID> machineIds = call.stop_maintenance().machines();
 
-
-  Future<Owned<ObjectApprover>> approver;
-
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    approver = master->authorizer.get()->getObjectApprover(
-        subject, authorization::STOP_MAINTENANCE);
-  } else {
-    approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  return approver.then(defer(
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {STOP_MAINTENANCE})
+    .then(defer(
       master->self(),
-      [this, machineIds](const Owned<ObjectApprover>& approver) {
-        return _stopMaintenance(machineIds, approver);
+      [this, machineIds](const Owned<ObjectApprovers>& approvers) {
+        return _stopMaintenance(machineIds, approvers);
       }));
 }
 
@@ -4997,24 +4644,16 @@ Future<Response> Master::Http::maintenanceStatus(
     return MethodNotAllowed({"GET"}, request.method);
   }
 
-  Future<Owned<ObjectApprover>> approver;
-
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    approver = master->authorizer.get()->getObjectApprover(
-        subject, authorization::GET_MAINTENANCE_STATUS);
-  } else {
-    approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
   Option<string> jsonp = request.url.query.get("jsonp");
 
-  return approver
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {GET_MAINTENANCE_STATUS})
     .then(defer(
       master->self(),
-      [this](const Owned<ObjectApprover>& approver) {
-        return _getMaintenanceStatus(approver);
+      [this](const Owned<ObjectApprovers>& approvers) {
+        return _getMaintenanceStatus(approvers);
       }))
     .then([jsonp](const mesos::maintenance::ClusterStatus& status) -> Response 
{
       return OK(JSON::protobuf(status), jsonp);
@@ -5023,7 +4662,7 @@ Future<Response> Master::Http::maintenanceStatus(
 
 
 Future<mesos::maintenance::ClusterStatus> Master::Http::_getMaintenanceStatus(
-    const Owned<ObjectApprover>& approver) const
+    const Owned<ObjectApprovers>& approvers) const
 {
   return master->allocator->getInverseOfferStatuses()
     .then(defer(
@@ -5040,16 +4679,7 @@ Future<mesos::maintenance::ClusterStatus> 
Master::Http::_getMaintenanceStatus(
         const MachineID& id,
         const Machine& machine,
         master->machines) {
-      Try<bool> approved = approver->approved(ObjectApprover::Object(id));
-
-      if (approved.isError()) {
-        LOG(WARNING) << "Error during MachineID authorization: "
-                     << approved.error();
-        // TODO(arojas): Consider exposing these errors to the caller.
-        continue;
-      }
-
-      if (!approved.get()) {
+      if (!approvers->approved<GET_MAINTENANCE_STATUS>(id)) {
         continue;
       }
 
@@ -5098,22 +4728,14 @@ Future<Response> Master::Http::getMaintenanceStatus(
 {
   CHECK_EQ(mesos::master::Call::GET_MAINTENANCE_STATUS, call.type());
 
-  Future<Owned<ObjectApprover>> approver;
-
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    approver = master->authorizer.get()->getObjectApprover(
-        subject, authorization::GET_MAINTENANCE_STATUS);
-  } else {
-    approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
-  return approver
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {GET_MAINTENANCE_STATUS})
     .then(defer(
       master->self(),
-      [this](const Owned<ObjectApprover>& approver) {
-        return _getMaintenanceStatus(approver);
+      [this](const Owned<ObjectApprovers>& approvers) {
+        return _getMaintenanceStatus(approvers);
       }))
     .then([contentType](const mesos::maintenance::ClusterStatus& status)
           -> Response {
@@ -5354,32 +4976,22 @@ Future<Response> Master::Http::markAgentGone(
 {
   CHECK_EQ(mesos::master::Call::MARK_AGENT_GONE, call.type());
 
-  Future<Owned<ObjectApprover>> approver;
-
-  if (master->authorizer.isSome()) {
-    Option<authorization::Subject> subject = createSubject(principal);
-
-    approver = master->authorizer.get()->getObjectApprover(
-        subject, authorization::MARK_AGENT_GONE);
-  } else {
-    approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
-  }
-
   const SlaveID& slaveId = call.mark_agent_gone().slave_id();
 
-  return approver.then(defer(master->self(),
-      [this, slaveId](const Owned<ObjectApprover>& approver)
+  return ObjectApprovers::create(
+      master->authorizer,
+      principal,
+      {MARK_AGENT_GONE})
+    .then(defer(
+      master->self(),
+      [this, slaveId](const Owned<ObjectApprovers>& approvers)
           -> Future<Response> {
-    Try<bool> approved = approver->approved((ObjectApprover::Object()));
-
-    if (approved.isError()) {
-      return InternalServerError("Authorization error: " + approved.error());
-    } else if (!approved.get()) {
-      return Forbidden();
-    }
+        if (!approvers->approved<MARK_AGENT_GONE>()) {
+          return Forbidden();
+        }
 
-    return _markAgentGone(slaveId);
-  }));
+        return _markAgentGone(slaveId);
+      }));
 }
 
 

Reply via email to