mesos-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ti...@apache.org
Subject [3/3] mesos git commit: Updated authorizer to allow for modularized implementations.
Date Thu, 13 Aug 2015 23:43:44 GMT
Updated authorizer to allow for modularized implementations.

Splits and updates the original declaration of the `Authorizer` into
its interface and a default implementation, the `LocalAuthorizer`.

Following the pattern of the modularized `Authenticator`, it generates
a default constructor which is required when writing a `TYPED_TEST` in
a follow up patch. Additionally, an initialize method has been added,
needed for passing in the current ACL definitions as provided via
flags.

Other changes are just updates to allow for compilation.

Review: https://reviews.apache.org/r/36048


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

Branch: refs/heads/master
Commit: f9a014b621e398bf4b063b4fa9157e40b087ff8f
Parents: dedd1ed
Author: Alexander Rojas <alexander@mesosphere.io>
Authored: Thu Aug 13 21:48:11 2015 +0200
Committer: Till Toenshoff <toenshoff@me.com>
Committed: Fri Aug 14 01:43:13 2015 +0200

----------------------------------------------------------------------
 include/mesos/authorizer/authorizer.hpp      | 144 +++++++++++
 include/mesos/authorizer/authorizer.proto    | 100 ++++++++
 include/mesos/mesos.proto                    |  75 ------
 include/mesos/type_utils.hpp                 |   6 -
 src/Makefile.am                              |  23 +-
 src/authorizer/authorizer.cpp                | 282 ---------------------
 src/authorizer/authorizer.hpp                |  87 -------
 src/authorizer/local/authorizer.cpp          | 296 ++++++++++++++++++++++
 src/authorizer/local/authorizer.hpp          |  74 ++++++
 src/common/parse.hpp                         |   2 +
 src/examples/persistent_volume_framework.cpp |   2 +
 src/local/local.cpp                          |  25 +-
 src/master/flags.hpp                         |   3 +
 src/master/http.cpp                          |   4 +-
 src/master/main.cpp                          |  25 +-
 src/master/master.cpp                        |   4 +-
 src/master/master.hpp                        |   5 +-
 src/tests/authorization_tests.cpp            |  92 +++++--
 src/tests/cluster.hpp                        |  23 +-
 src/tests/mesos.cpp                          |   4 +-
 src/tests/mesos.hpp                          |   9 +-
 21 files changed, 778 insertions(+), 507 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/include/mesos/authorizer/authorizer.hpp
----------------------------------------------------------------------
diff --git a/include/mesos/authorizer/authorizer.hpp b/include/mesos/authorizer/authorizer.hpp
new file mode 100644
index 0000000..6ee23c1
--- /dev/null
+++ b/include/mesos/authorizer/authorizer.hpp
@@ -0,0 +1,144 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MESOS_AUTHORIZER_AUTHORIZER_HPP__
+#define __MESOS_AUTHORIZER_AUTHORIZER_HPP__
+
+#include <ostream>
+
+// ONLY USEFUL AFTER RUNNING PROTOC.
+#include <mesos/authorizer/authorizer.pb.h>
+
+#include <process/future.hpp>
+
+#include <stout/nothing.hpp>
+#include <stout/option.hpp>
+#include <stout/try.hpp>
+
+namespace mesos {
+
+/**
+ * An interface used to provide authorization for actions with ACLs.
+ * Refer to "docs/authorization.md" for the details regarding the
+ * authorization mechanism.
+ *
+ * @see docs/authorization.md
+ */
+class Authorizer
+{
+public:
+  virtual ~Authorizer() {}
+
+  /**
+   * Only relevant for the default implementation of the Authorizer class
+   * (MESOS-3072) and it will not be called for any other implementation.
+   *
+   * Sets the Access Control Lists for the current instance of the interface.
+   * The contents of the acls parameter are used to define the rules which apply
+   * to the authorization actions. Please check the 'authorizer.proto' file to
+   * review their format, and the 'docs/authorization.md' for a description on
+   * how authorization is performed.
+   *
+   * @param acls The access control lists used to initialize the authorizer
+   *     instance. See the autorizer.proto file for a description on their
+   *     format.
+   *
+   * @return Nothing if the instance of the authorizer was successfully
+   +     initialized, an Error otherwise.
+   *
+   * TODO(arojas): Remove once we have a module only initialization which would
+   * rely only module specific parameters as supplied via the modules JSON blob
+   * (see MESOS-3072).
+   */
+  virtual Try<Nothing> initialize(const Option<ACLs>& acls) = 0;
+
+  /**
+   * Used to verify if a principal is allowed to register a framework with a
+   * specific role. The principal and role parameters are packed in the request.
+   * If the principal is allowed to perform the action, this method returns
+   * true. Otherwise it returns false. A third possible outcome is that the
+   * future fails. Then it indicates the request could not be checked at the
+   * moment. This may be a temporary condition.
+   *
+   * @param request An instance of an ACL::RegisterFramework protobuf message.
+   *     It packs all the parameters needed to verify if the principal is
+   *     allowed to register a framework with the specified role.
+   *
+   * @return true if the principal is allowed to register the framework with the
+   *     specified role or false otherwise. A failed future is neither true
+   *     nor false. It indicates a problem processing the request and the
+   *     request can be retried.
+   */
+  virtual process::Future<bool> authorize(
+      const ACL::RegisterFramework& request) = 0;
+
+  /**
+   * Used to verify if a principal is allowed to run tasks as the given UNIX
+   * user. The principal and user parameters are packed in the request. If the
+   * principal is allowed to perform the action, this method returns true.
+   * Otherwise it returns false. A third possible outcome is that the future
+   * fails. Then it indicates the request could not be checked at the moment.
+   * This may be a temporary condition.
+   *
+   * @param request An instance of an ACL::RunTask protobuf message. It packs
+   *     all the parameters needed to verify if a principal can launch a task
+   *     using the specified UNIX user.
+   *
+   * @return true if the principal is allowed to run a task using the given
+   *     UNIX user name, false otherwise. A failed future is neither true
+   *     nor false. It indicates a problem processing the request and the
+   *     request can be retried.
+   */
+  virtual process::Future<bool> authorize(
+      const ACL::RunTask& request) = 0;
+
+  /**
+   * Used to verify if a principal is allowed to shut down a framework launched
+   * by the given framework_principal. The principal and framework_principal
+   * parameters are packed in the request. If the principal is allowed to
+   * perform the action, this method returns true. Otherwise it returns false.
+   * A third possible outcome is that the future fails. Then it indicates the
+   * request could not be checked at the moment. This may be a temporary
+   * condition.
+   *
+   * @param request An instance of an ACL::RunTask protobuf message. It packs
+   *     all the parameters needed to verify the given principal is allowed to
+   *     shut down a framework launched by the framework principal, i.e. the
+   *     principal who originally registered the framework.
+   *
+   * @return true if the principal can shutdown a framework ran by the
+   *     framework_principal, false otherwise. A failed future is neither true
+   *     nor false. It indicates a problem processing the request and the
+   *     request can be retried.
+   */
+  virtual process::Future<bool> authorize(
+      const ACL::ShutdownFramework& request) = 0;
+
+protected:
+  Authorizer() {}
+};
+
+
+inline std::ostream& operator<<(std::ostream& stream, const ACLs& acls)
+{
+  return stream << acls.DebugString();
+}
+
+} // namespace mesos {
+
+#endif // __MESOS_AUTHORIZER_AUTHORIZER_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/include/mesos/authorizer/authorizer.proto
----------------------------------------------------------------------
diff --git a/include/mesos/authorizer/authorizer.proto b/include/mesos/authorizer/authorizer.proto
new file mode 100644
index 0000000..86bbb45
--- /dev/null
+++ b/include/mesos/authorizer/authorizer.proto
@@ -0,0 +1,100 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import "mesos/mesos.proto";
+
+package mesos;
+
+option java_package = "org.apache.mesos";
+option java_outer_classname = "Protos";
+
+
+/**
+ * ACLs used for local authorization (See authorization.md file in the
+ * docs).
+ */
+message ACL {
+
+  // Entity is used to describe a subject(s) or an object(s) of an ACL.
+  // NOTE:
+  // To allow everyone access to an Entity set its type to 'ANY'.
+  // To deny access to an Entity set its type to 'NONE'.
+  message Entity {
+    enum Type {
+      SOME = 0;
+      ANY = 1;
+      NONE = 2;
+    }
+    optional Type type = 1 [default = SOME];
+    repeated string values = 2; // Ignored for ANY/NONE.
+  }
+
+  // ACLs.
+  message RegisterFramework {
+    // Subjects.
+    required Entity principals = 1; // Framework principals.
+
+    // Objects.
+    required Entity roles = 2; // Roles for resource offers.
+  }
+
+  message RunTask {
+    // Subjects.
+    required Entity principals = 1; // Framework principals.
+
+    // Objects.
+    required Entity users = 2; // Users to run the tasks/executors as.
+  }
+
+  // Which principals are authorized to shutdown frameworks of other
+  // principals.
+  message ShutdownFramework {
+    // Subjects.
+    required Entity principals = 1;
+
+    // Objects.
+    required Entity framework_principals = 2;
+  }
+}
+
+
+/**
+ * Collection of ACL.
+ *
+ * Each authorization request is evaluated against the ACLs in the order
+ * they are defined.
+ *
+ * For simplicity, the ACLs for a given action are not aggregated even
+ * when they have the same subjects or objects. The first ACL that
+ * matches the request determines whether that request should be
+ * permitted or not. An ACL matches iff both the subjects
+ * (e.g., clients, principals) and the objects (e.g., urls, users,
+ * roles) of the ACL match the request.
+ *
+ * If none of the ACLs match the request, the 'permissive' field
+ * determines whether the request should be permitted or not.
+ *
+ * TODO(vinod): Do aggregation of ACLs when possible.
+ *
+ */
+message ACLs {
+  optional bool permissive = 1 [default = true];
+  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/f9a014b6/include/mesos/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/mesos.proto b/include/mesos/mesos.proto
index 62bb3e7..ea9c760 100644
--- a/include/mesos/mesos.proto
+++ b/include/mesos/mesos.proto
@@ -1073,81 +1073,6 @@ message Credentials {
 
 
 /**
- * ACLs used for authorization.
- */
-message ACL {
-
-  // Entity is used to describe a subject(s) or an object(s) of an ACL.
-  // NOTE:
-  // To allow everyone access to an Entity set its type to 'ANY'.
-  // To deny access to an Entity set its type to 'NONE'.
-  message Entity {
-    enum Type {
-      SOME = 0;
-      ANY = 1;
-      NONE = 2;
-    }
-    optional Type type = 1 [default = SOME];
-    repeated string values = 2; // Ignored for ANY/NONE.
-  }
-
-  // ACLs.
-  message RegisterFramework {
-    // Subjects.
-    required Entity principals = 1; // Framework principals.
-
-    // Objects.
-    required Entity roles = 2; // Roles for resource offers.
-  }
-
-  message RunTask {
-    // Subjects.
-    required Entity principals = 1; // Framework principals.
-
-    // Objects.
-    required Entity users = 2; // Users to run the tasks/executors as.
-  }
-
-  // Which principals are authorized to shutdown frameworks of other
-  // principals.
-  message ShutdownFramework {
-    // Subjects.
-    required Entity principals = 1;
-
-    // Objects.
-    required Entity framework_principals = 2;
-  }
-}
-
-
-/**
- * Collection of ACL.
- *
- * Each authorization request is evaluated against the ACLs in the order
- * they are defined.
- *
- * For simplicity, the ACLs for a given action are not aggregated even
- * when they have the same subjects or objects. The first ACL that
- * matches the request determines whether that request should be
- * permitted or not. An ACL matches iff both the subjects
- * (e.g., clients, principals) and the objects (e.g., urls, users,
- * roles) of the ACL match the request.
- *
- * If none of the ACLs match the request, the 'permissive' field
- * determines whether the request should be permitted or not.
- *
- * TODO(vinod): Do aggregation of ACLs when possible.
- *
- */
-message ACLs {
-  optional bool permissive = 1 [default = true];
-  repeated ACL.RegisterFramework register_frameworks = 2;
-  repeated ACL.RunTask run_tasks = 3;
-  repeated ACL.ShutdownFramework shutdown_frameworks = 4;
-}
-
-
-/**
  * Rate (queries per second, QPS) limit for messages from a framework to master.
  * Strictly speaking they are the combined rate from all frameworks of the same
  * principal.

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/include/mesos/type_utils.hpp
----------------------------------------------------------------------
diff --git a/include/mesos/type_utils.hpp b/include/mesos/type_utils.hpp
index 6ff061c..dafe1df 100644
--- a/include/mesos/type_utils.hpp
+++ b/include/mesos/type_utils.hpp
@@ -268,12 +268,6 @@ inline std::size_t hash_value(const TaskID& taskId)
 }
 
 
-inline std::ostream& operator<<(std::ostream& stream, const ACLs& acls)
-{
-  return stream << acls.DebugString();
-}
-
-
 inline std::ostream& operator<<(
     std::ostream& stream,
     const ContainerID& containerId)

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index b5dbdc3..c481b6f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -141,6 +141,9 @@ V1_MESOS_PROTO = $(top_srcdir)/include/mesos/v1/mesos.proto
 AUTHENTICATION_PROTO =							\
   $(top_srcdir)/include/mesos/authentication/authentication.proto
 
+AUTHORIZATION_PROTO =							\
+  $(top_srcdir)/include/mesos/authorizer/authorizer.proto
+
 CONTAINERIZER_PROTO =							\
   $(top_srcdir)/include/mesos/containerizer/containerizer.proto
 
@@ -173,6 +176,8 @@ CXX_PROTOS =								\
   ../include/mesos/mesos.pb.h						\
   authentication/authentication.pb.cc					\
   ../include/mesos/authentication/authentication.pb.h			\
+  authorizer/authorizer.pb.cc						\
+  ../include/mesos/authorizer/authorizer.pb.h				\
   containerizer/containerizer.pb.cc					\
   ../include/mesos/containerizer/containerizer.pb.h			\
   executor/executor.pb.cc						\
@@ -249,6 +254,12 @@ authentication/%.pb.cc ../include/mesos/authentication/%.pb.h: $(AUTHENTICATION_
 	$(PROTOC) $(PROTOCFLAGS) --cpp_out=../include $^
 	mv ../include/mesos/authentication/*.pb.cc $(@D)
 
+authorizer/%.pb.cc ../include/mesos/authorizer/%.pb.h: $(AUTHORIZATION_PROTO)
+	$(MKDIR_P) $(@D)
+	$(MKDIR_P) ../include/mesos/authorizer
+	$(PROTOC) $(PROTOCFLAGS) --cpp_out=../include $^
+	mv ../include/mesos/authorizer/*.pb.cc $(@D)
+
 containerizer/%.pb.cc ../include/mesos/containerizer/%.pb.h: $(CONTAINERIZER_PROTO)
 	$(MKDIR_P) $(@D)
 	$(MKDIR_P) ../include/mesos/containerizer
@@ -391,7 +402,7 @@ libmesos_no_3rdparty_la_SOURCES =					\
 	authentication/cram_md5/authenticatee.cpp			\
 	authentication/cram_md5/authenticator.cpp			\
 	authentication/cram_md5/auxprop.cpp				\
-	authorizer/authorizer.cpp					\
+	authorizer/local/authorizer.cpp					\
 	common/attributes.cpp						\
 	common/date_utils.cpp						\
 	common/http.cpp							\
@@ -499,6 +510,14 @@ authentication_HEADERS =						\
 
 nodist_authentication_HEADERS = ../include/mesos/authentication/authentication.pb.h
 
+authorizerdir = $(pkgincludedir)/authorizer
+
+authorizer_HEADERS =							\
+  $(top_srcdir)/include/mesos/authorizer/authorizer.hpp			\
+  $(top_srcdir)/include/mesos/authorizer/authorizer.proto
+
+nodist_authorizer_HEADERS = ../include/mesos/authorizer/authorizer.pb.h
+
 containerizerdir = $(pkgincludedir)/containerizer
 
 containerizer_HEADERS =							\
@@ -651,7 +670,7 @@ libmesos_no_3rdparty_la_SOURCES +=					\
 	authentication/cram_md5/authenticatee.hpp			\
 	authentication/cram_md5/authenticator.hpp			\
 	authentication/cram_md5/auxprop.hpp				\
-	authorizer/authorizer.hpp					\
+	authorizer/local/authorizer.hpp					\
 	common/attributes.hpp						\
 	common/build.hpp						\
 	common/date_utils.hpp						\

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/authorizer/authorizer.cpp
----------------------------------------------------------------------
diff --git a/src/authorizer/authorizer.cpp b/src/authorizer/authorizer.cpp
deleted file mode 100644
index 21e97e3..0000000
--- a/src/authorizer/authorizer.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string>
-#include <vector>
-
-#include <glog/logging.h>
-
-#include <process/dispatch.hpp>
-#include <process/future.hpp>
-#include <process/id.hpp>
-#include <process/owned.hpp>
-#include <process/process.hpp>
-#include <process/protobuf.hpp>
-
-#include <stout/check.hpp>
-#include <stout/hashmap.hpp>
-#include <stout/hashset.hpp>
-#include <stout/protobuf.hpp>
-#include <stout/try.hpp>
-
-#include "authorizer/authorizer.hpp"
-
-#include "mesos/mesos.hpp"
-
-using process::Future;
-using process::Owned;
-using process::dispatch;
-
-using std::string;
-using std::vector;
-
-namespace mesos {
-namespace internal {
-
-class LocalAuthorizerProcess : public ProtobufProcess<LocalAuthorizerProcess>
-{
-public:
-  LocalAuthorizerProcess(const ACLs& _acls)
-    : ProcessBase(process::ID::generate("authorizer")), acls(_acls) {}
-
-  Future<bool> authorize(const ACL::RegisterFramework& request)
-  {
-    foreach (const ACL::RegisterFramework& acl, acls.register_frameworks()) {
-      // ACL matches if both subjects and objects match.
-      if (matches(request.principals(), acl.principals()) &&
-          matches(request.roles(), acl.roles())) {
-        // ACL is allowed if both subjects and objects are allowed.
-        return allows(request.principals(), acl.principals()) &&
-               allows(request.roles(), acl.roles());
-      }
-    }
-
-    return acls.permissive(); // None of the ACLs match.
-  }
-
-  Future<bool> authorize(const ACL::RunTask& request)
-  {
-    foreach (const ACL::RunTask& acl, acls.run_tasks()) {
-      // ACL matches if both subjects and objects match.
-      if (matches(request.principals(), acl.principals()) &&
-          matches(request.users(), acl.users())) {
-        // ACL is allowed if both subjects and objects are allowed.
-        return allows(request.principals(), acl.principals()) &&
-               allows(request.users(), acl.users());
-      }
-    }
-
-    return acls.permissive(); // None of the ACLs match.
-  }
-
-  Future<bool> authorize(const ACL::ShutdownFramework& request)
-  {
-    foreach (const ACL::ShutdownFramework& acl, acls.shutdown_frameworks()) {
-      // ACL matches if both subjects and objects match.
-      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.principals(), acl.principals()) &&
-               allows(request.framework_principals(),
-                      acl.framework_principals());
-      }
-    }
-
-    return acls.permissive(); // None of the ACLs match.
-  }
-
-private:
-  // Match matrix:
-  //
-  //                  -----------ACL----------
-  //
-  //                    SOME    NONE    ANY
-  //          -------|-------|-------|-------
-  //  |        SOME  | Yes/No|  Yes  |   Yes
-  //  |       -------|-------|-------|-------
-  // Request   NONE  |  No   |  Yes  |   No
-  //  |       -------|-------|-------|-------
-  //  |        ANY   |  No   |  Yes  |   Yes
-  //          -------|-------|-------|-------
-  bool matches(const ACL::Entity& request, const ACL::Entity& acl)
-  {
-    // NONE only matches with NONE.
-    if (request.type() == ACL::Entity::NONE) {
-      return acl.type() == ACL::Entity::NONE;
-    }
-
-    // ANY matches with ANY or NONE.
-    if (request.type() == ACL::Entity::ANY) {
-      return acl.type() == ACL::Entity::ANY || acl.type() == ACL::Entity::NONE;
-    }
-
-    if (request.type() == ACL::Entity::SOME) {
-      // SOME matches with ANY or NONE.
-      if (acl.type() == ACL::Entity::ANY || acl.type() == ACL::Entity::NONE) {
-        return true;
-      }
-
-      // SOME is allowed if the request values are a subset of ACL
-      // values.
-      foreach (const string& value, request.values()) {
-        bool found = false;
-        foreach (const string& value_, acl.values()) {
-          if (value == value_) {
-            found = true;
-            break;
-          }
-        }
-
-        if (!found) {
-          return false;
-        }
-      }
-      return true;
-    }
-
-    return false;
-  }
-
-  // Allow matrix:
-  //
-  //                 -----------ACL----------
-  //
-  //                    SOME    NONE    ANY
-  //          -------|-------|-------|-------
-  //  |        SOME  | Yes/No|  No   |   Yes
-  //  |       -------|-------|-------|-------
-  // Request   NONE  |  No   |  Yes  |   No
-  //  |       -------|-------|-------|-------
-  //  |        ANY   |  No   |  No   |   Yes
-  //          -------|-------|-------|-------
-  bool allows(const ACL::Entity& request, const ACL::Entity& acl)
-  {
-    // NONE is only allowed by NONE.
-    if (request.type() == ACL::Entity::NONE) {
-      return acl.type() == ACL::Entity::NONE;
-    }
-
-    // ANY is only allowed by ANY.
-    if (request.type() == ACL::Entity::ANY) {
-      return acl.type() == ACL::Entity::ANY;
-    }
-
-    if (request.type() == ACL::Entity::SOME) {
-      // SOME is allowed by ANY.
-      if (acl.type() == ACL::Entity::ANY) {
-        return true;
-      }
-
-      // SOME is not allowed by NONE.
-      if (acl.type() == ACL::Entity::NONE) {
-        return false;
-      }
-
-      // SOME is allowed if the request values are a subset of ACL
-      // values.
-      foreach (const string& value, request.values()) {
-        bool found = false;
-        foreach (const string& value_, acl.values()) {
-          if (value == value_) {
-            found = true;
-            break;
-          }
-        }
-
-        if (!found) {
-          return false;
-        }
-      }
-      return true;
-    }
-
-    return false;
-  }
-
-  ACLs acls;
-};
-
-
-Try<Owned<Authorizer> > Authorizer::create(const ACLs& acls)
-{
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-
-  if (authorizer.isError()) {
-    return Error(authorizer.error());
-  }
-
-  Owned<LocalAuthorizer> authorizer_ = authorizer.get();
-  return static_cast<Authorizer*>(authorizer_.release());
-}
-
-
-LocalAuthorizer::LocalAuthorizer(const ACLs& acls)
-{
-  process = new LocalAuthorizerProcess(acls);
-  spawn(process);
-}
-
-
-LocalAuthorizer::~LocalAuthorizer()
-{
-  terminate(process);
-  wait(process);
-  delete process;
-}
-
-
-Try<Owned<LocalAuthorizer> > LocalAuthorizer::create(const ACLs& acls)
-{
-  return new LocalAuthorizer(acls);
-}
-
-
-Future<bool> LocalAuthorizer::authorize(const ACL::RegisterFramework& request)
-{
-  // Necessary to disambiguate.
-  typedef Future<bool>(LocalAuthorizerProcess::*F)(
-      const ACL::RegisterFramework&);
-
-  return dispatch(
-      process, static_cast<F>(&LocalAuthorizerProcess::authorize), request);
-}
-
-
-Future<bool> LocalAuthorizer::authorize(const ACL::RunTask& request)
-{
-  // Necessary to disambiguate.
-  typedef Future<bool>(LocalAuthorizerProcess::*F)(const ACL::RunTask&);
-
-  return dispatch(
-      process, static_cast<F>(&LocalAuthorizerProcess::authorize), request);
-}
-
-
-Future<bool> LocalAuthorizer::authorize(const ACL::ShutdownFramework& request)
-{
-  // Necessary to disambiguate.
-  typedef Future<bool>(LocalAuthorizerProcess::*F)(
-      const ACL::ShutdownFramework&);
-
-  return dispatch(
-      process, static_cast<F>(&LocalAuthorizerProcess::authorize), request);
-}
-
-} // namespace internal {
-} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/authorizer/authorizer.hpp
----------------------------------------------------------------------
diff --git a/src/authorizer/authorizer.hpp b/src/authorizer/authorizer.hpp
deleted file mode 100644
index c039d94..0000000
--- a/src/authorizer/authorizer.hpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __AUTHORIZER_AUTHORIZER_HPP__
-#define __AUTHORIZER_AUTHORIZER_HPP__
-
-#include <glog/logging.h>
-
-#include <process/future.hpp>
-#include <process/owned.hpp>
-#include <process/process.hpp>
-
-#include <stout/json.hpp>
-#include <stout/try.hpp>
-
-#include "mesos/mesos.hpp"
-
-namespace mesos {
-namespace internal {
-
-// Forward declaration.
-class LocalAuthorizerProcess;
-
-
-class Authorizer
-{
-public:
-  virtual ~Authorizer() {}
-
-  // Attempts to create an Authorizer based on the ACLs.
-  static Try<process::Owned<Authorizer> > create(const ACLs& acls);
-
-  // Returns true if the ACL can be satisfied or false otherwise.
-  // A failed future indicates a transient failure and the user
-  // can (should) retry.
-  virtual process::Future<bool> authorize(
-      const ACL::RegisterFramework& request) = 0;
-  virtual process::Future<bool> authorize(
-      const ACL::RunTask& request) = 0;
-  virtual process::Future<bool> authorize(
-      const ACL::ShutdownFramework& request) = 0;
-
-protected:
-  Authorizer() {}
-};
-
-
-// This Authorizer is constructed with all the required ACLs upfront.
-class LocalAuthorizer : public Authorizer
-{
-public:
-  // Validates the ACLs and creates a LocalAuthorizer.
-  static Try<process::Owned<LocalAuthorizer> > create(const ACLs& acls);
-  virtual ~LocalAuthorizer();
-
-  // Implementation of Authorizer interface.
-  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);
-  LocalAuthorizerProcess* process;
-};
-
-} // namespace internal {
-} // namespace mesos {
-
-#endif //__AUTHORIZER_AUTHORIZER_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/authorizer/local/authorizer.cpp
----------------------------------------------------------------------
diff --git a/src/authorizer/local/authorizer.cpp b/src/authorizer/local/authorizer.cpp
new file mode 100644
index 0000000..6d7da87
--- /dev/null
+++ b/src/authorizer/local/authorizer.cpp
@@ -0,0 +1,296 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "authorizer/local/authorizer.hpp"
+
+#include <string>
+
+#include <process/dispatch.hpp>
+#include <process/future.hpp>
+#include <process/id.hpp>
+#include <process/process.hpp>
+#include <process/protobuf.hpp>
+
+#include <stout/protobuf.hpp>
+#include <stout/try.hpp>
+
+using process::Failure;
+using process::Future;
+using process::dispatch;
+
+using std::string;
+
+namespace mesos {
+namespace internal {
+
+class LocalAuthorizerProcess : public ProtobufProcess<LocalAuthorizerProcess>
+{
+public:
+  LocalAuthorizerProcess(const ACLs& _acls)
+    : ProcessBase(process::ID::generate("authorizer")), acls(_acls) {}
+
+  Future<bool> authorize(const ACL::RegisterFramework& request)
+  {
+    foreach (const ACL::RegisterFramework& acl, acls.register_frameworks()) {
+      // ACL matches if both subjects and objects match.
+      if (matches(request.principals(), acl.principals()) &&
+          matches(request.roles(), acl.roles())) {
+        // ACL is allowed if both subjects and objects are allowed.
+        return allows(request.principals(), acl.principals()) &&
+               allows(request.roles(), acl.roles());
+      }
+    }
+
+    return acls.permissive(); // None of the ACLs match.
+  }
+
+  Future<bool> authorize(const ACL::RunTask& request)
+  {
+    foreach (const ACL::RunTask& acl, acls.run_tasks()) {
+      // ACL matches if both subjects and objects match.
+      if (matches(request.principals(), acl.principals()) &&
+          matches(request.users(), acl.users())) {
+        // ACL is allowed if both subjects and objects are allowed.
+        return allows(request.principals(), acl.principals()) &&
+               allows(request.users(), acl.users());
+      }
+    }
+
+    return acls.permissive(); // None of the ACLs match.
+  }
+
+  Future<bool> authorize(const ACL::ShutdownFramework& request)
+  {
+    foreach (const ACL::ShutdownFramework& acl, acls.shutdown_frameworks()) {
+      // ACL matches if both subjects and objects match.
+      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.principals(), acl.principals()) &&
+               allows(request.framework_principals(),
+                      acl.framework_principals());
+      }
+    }
+
+    return acls.permissive(); // None of the ACLs match.
+  }
+
+private:
+  // Match matrix:
+  //
+  //                  -----------ACL----------
+  //
+  //                    SOME    NONE    ANY
+  //          -------|-------|-------|-------
+  //  |        SOME  | Yes/No|  Yes  |   Yes
+  //  |       -------|-------|-------|-------
+  // Request   NONE  |  No   |  Yes  |   No
+  //  |       -------|-------|-------|-------
+  //  |        ANY   |  No   |  Yes  |   Yes
+  //          -------|-------|-------|-------
+  bool matches(const ACL::Entity& request, const ACL::Entity& acl)
+  {
+    // NONE only matches with NONE.
+    if (request.type() == ACL::Entity::NONE) {
+      return acl.type() == ACL::Entity::NONE;
+    }
+
+    // ANY matches with ANY or NONE.
+    if (request.type() == ACL::Entity::ANY) {
+      return acl.type() == ACL::Entity::ANY || acl.type() == ACL::Entity::NONE;
+    }
+
+    if (request.type() == ACL::Entity::SOME) {
+      // SOME matches with ANY or NONE.
+      if (acl.type() == ACL::Entity::ANY || acl.type() == ACL::Entity::NONE) {
+        return true;
+      }
+
+      // SOME is allowed if the request values are a subset of ACL
+      // values.
+      foreach (const string& value, request.values()) {
+        bool found = false;
+        foreach (const string& value_, acl.values()) {
+          if (value == value_) {
+            found = true;
+            break;
+          }
+        }
+
+        if (!found) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    return false;
+  }
+
+  // Allow matrix:
+  //
+  //                 -----------ACL----------
+  //
+  //                    SOME    NONE    ANY
+  //          -------|-------|-------|-------
+  //  |        SOME  | Yes/No|  No   |   Yes
+  //  |       -------|-------|-------|-------
+  // Request   NONE  |  No   |  Yes  |   No
+  //  |       -------|-------|-------|-------
+  //  |        ANY   |  No   |  No   |   Yes
+  //          -------|-------|-------|-------
+  bool allows(const ACL::Entity& request, const ACL::Entity& acl)
+  {
+    // NONE is only allowed by NONE.
+    if (request.type() == ACL::Entity::NONE) {
+      return acl.type() == ACL::Entity::NONE;
+    }
+
+    // ANY is only allowed by ANY.
+    if (request.type() == ACL::Entity::ANY) {
+      return acl.type() == ACL::Entity::ANY;
+    }
+
+    if (request.type() == ACL::Entity::SOME) {
+      // SOME is allowed by ANY.
+      if (acl.type() == ACL::Entity::ANY) {
+        return true;
+      }
+
+      // SOME is not allowed by NONE.
+      if (acl.type() == ACL::Entity::NONE) {
+        return false;
+      }
+
+      // SOME is allowed if the request values are a subset of ACL
+      // values.
+      foreach (const string& value, request.values()) {
+        bool found = false;
+        foreach (const string& value_, acl.values()) {
+          if (value == value_) {
+            found = true;
+            break;
+          }
+        }
+
+        if (!found) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    return false;
+  }
+
+  ACLs acls;
+};
+
+
+Try<Authorizer*> LocalAuthorizer::create()
+{
+  Authorizer* local = new LocalAuthorizer;
+
+  return local;
+}
+
+
+LocalAuthorizer::LocalAuthorizer() : process(NULL)
+{
+}
+
+
+LocalAuthorizer::~LocalAuthorizer()
+{
+  if (process != NULL) {
+    terminate(process);
+    wait(process);
+    delete process;
+  }
+}
+
+Try<Nothing> LocalAuthorizer::initialize(const Option<ACLs>& acls)
+{
+  if (!acls.isSome()) {
+    return Error("ACLs need to be specified for local authorizer");
+  }
+
+  if (!initialized.once()) {
+    if (process != NULL) {
+      return Error("Authorizer already initialized");
+    }
+
+    // Process initialization needs to be done here because default
+    // implementations of modules need to be default constructible. So
+    // actual construction is delayed until initialization.
+    process = new LocalAuthorizerProcess(acls.get());
+    spawn(process);
+
+    initialized.done();
+  }
+
+  return Nothing();
+}
+
+
+Future<bool> LocalAuthorizer::authorize(const ACL::RegisterFramework& request)
+{
+  if (process == NULL) {
+    return Failure("Authorizer not initialized");
+  }
+
+  // Necessary to disambiguate.
+  typedef Future<bool>(LocalAuthorizerProcess::*F)(
+      const ACL::RegisterFramework&);
+
+  return dispatch(
+      process, static_cast<F>(&LocalAuthorizerProcess::authorize), request);
+}
+
+
+Future<bool> LocalAuthorizer::authorize(const ACL::RunTask& request)
+{
+  if (process == NULL) {
+    return Failure("Authorizer not initialized");
+  }
+
+  // Necessary to disambiguate.
+  typedef Future<bool>(LocalAuthorizerProcess::*F)(const ACL::RunTask&);
+
+  return dispatch(
+      process, static_cast<F>(&LocalAuthorizerProcess::authorize), request);
+}
+
+
+Future<bool> LocalAuthorizer::authorize(const ACL::ShutdownFramework& request)
+{
+  if (process == NULL) {
+    return Failure("Authorizer not initialized");
+  }
+
+  // Necessary to disambiguate.
+  typedef Future<bool>(LocalAuthorizerProcess::*F)(
+      const ACL::ShutdownFramework&);
+
+  return dispatch(
+      process, static_cast<F>(&LocalAuthorizerProcess::authorize), request);
+}
+
+} // namespace internal {
+} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/authorizer/local/authorizer.hpp
----------------------------------------------------------------------
diff --git a/src/authorizer/local/authorizer.hpp b/src/authorizer/local/authorizer.hpp
new file mode 100644
index 0000000..32de102
--- /dev/null
+++ b/src/authorizer/local/authorizer.hpp
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __AUTHORIZER_AUTHORIZER_HPP__
+#define __AUTHORIZER_AUTHORIZER_HPP__
+
+#include <mesos/authorizer/authorizer.hpp>
+
+#include <process/future.hpp>
+#include <process/once.hpp>
+
+#include <stout/nothing.hpp>
+#include <stout/option.hpp>
+#include <stout/try.hpp>
+
+namespace mesos {
+namespace internal {
+
+// Forward declaration.
+class LocalAuthorizerProcess;
+
+// This Authorizer is constructed with all the required ACLs upfront.
+class LocalAuthorizer : public Authorizer
+{
+public:
+  // Creates a LocalAuthorizer.
+  // Never returns a nullptr, instead sets the Try to error.
+  //
+  // This factory needs to return a raw pointer so its signature matches that
+  // of tests::Module<T,N>::create() so typed tests can be performed.
+  static Try<Authorizer*> create();
+
+  virtual ~LocalAuthorizer();
+
+  // Initialization is needed since this class is required to be default
+  // constructible, however the ACLs still need to be provided. MESOS-3072
+  // tries to address this requirement.
+  virtual Try<Nothing> initialize(const Option<ACLs>& acls);
+
+  // Implementation of Authorizer interface.
+  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();
+
+  LocalAuthorizerProcess* process;
+
+  process::Once initialized;
+};
+
+} // namespace internal {
+} // namespace mesos {
+
+#endif //__AUTHORIZER_AUTHORIZER_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/common/parse.hpp
----------------------------------------------------------------------
diff --git a/src/common/parse.hpp b/src/common/parse.hpp
index 8d7ddd6..77aeefb 100644
--- a/src/common/parse.hpp
+++ b/src/common/parse.hpp
@@ -16,6 +16,8 @@
 
 #include <mesos/mesos.hpp>
 
+#include <mesos/authorizer/authorizer.hpp>
+
 #include <mesos/module/module.hpp>
 
 #include <stout/error.hpp>

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/examples/persistent_volume_framework.cpp
----------------------------------------------------------------------
diff --git a/src/examples/persistent_volume_framework.cpp b/src/examples/persistent_volume_framework.cpp
index c6d6ed3..426d338 100644
--- a/src/examples/persistent_volume_framework.cpp
+++ b/src/examples/persistent_volume_framework.cpp
@@ -28,6 +28,8 @@
 #include <mesos/scheduler.hpp>
 #include <mesos/type_utils.hpp>
 
+#include <mesos/authorizer/authorizer.hpp>
+
 #include <stout/flags.hpp>
 #include <stout/format.hpp>
 #include <stout/json.hpp>

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/local/local.cpp
----------------------------------------------------------------------
diff --git a/src/local/local.cpp b/src/local/local.cpp
index 1953d84..0390140 100644
--- a/src/local/local.cpp
+++ b/src/local/local.cpp
@@ -23,6 +23,8 @@
 #include <string>
 #include <vector>
 
+#include <mesos/authorizer/authorizer.hpp>
+
 #include <mesos/master/allocator.hpp>
 
 #include <mesos/module/anonymous.hpp>
@@ -41,7 +43,7 @@
 #include <stout/try.hpp>
 #include <stout/strings.hpp>
 
-#include "authorizer/authorizer.hpp"
+#include "authorizer/local/authorizer.hpp"
 
 #include "common/protobuf_utils.hpp"
 
@@ -214,16 +216,23 @@ PID<Master> launch(const Flags& flags, Allocator* _allocator)
     detector = new StandaloneMasterDetector();
 
     if (flags.acls.isSome()) {
-      Try<Owned<Authorizer>> create = Authorizer::create(flags.acls.get());
+      Try<Authorizer*> local = LocalAuthorizer::create();
 
-      if (create.isError()) {
-        EXIT(1) << "Failed to initialize the authorizer: "
-                << create.error() << " (see --acls flag)";
+      if (local.isError()) {
+        EXIT(EXIT_FAILURE)
+          << "Failed to instantiate the local authorizer: "
+          << local.error();
       }
 
-      // Now pull out the authorizer but need to make a copy since we
-      // get a 'const &' from 'Try::get'.
-      authorizer = Owned<Authorizer>(create.get()).release();
+      authorizer = local.get();
+
+      Try<Nothing> initialized = authorizer.get()->initialize(flags.acls.get());
+
+      if (initialized.isError()) {
+        EXIT(EXIT_FAILURE)
+          << "Failed to initialize the local authorizer: "
+          << initialized.error() << " (see --acls flag)";
+      }
     }
 
     Option<shared_ptr<RateLimiter>> slaveRemovalLimiter = None();

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/master/flags.hpp
----------------------------------------------------------------------
diff --git a/src/master/flags.hpp b/src/master/flags.hpp
index f2cd19a..25e4631 100644
--- a/src/master/flags.hpp
+++ b/src/master/flags.hpp
@@ -26,6 +26,9 @@
 #include <stout/path.hpp>
 
 #include <mesos/mesos.hpp>
+
+#include <mesos/authorizer/authorizer.hpp>
+
 #include <mesos/module/module.hpp>
 
 #include "logging/flags.hpp"

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/master/http.cpp
----------------------------------------------------------------------
diff --git a/src/master/http.cpp b/src/master/http.cpp
index 2749871..190248c 100644
--- a/src/master/http.cpp
+++ b/src/master/http.cpp
@@ -28,6 +28,8 @@
 
 #include <mesos/type_utils.hpp>
 
+#include <mesos/authorizer/authorizer.hpp>
+
 #include <process/help.hpp>
 
 #include <process/metrics/metrics.hpp>
@@ -42,8 +44,6 @@
 #include <stout/result.hpp>
 #include <stout/strings.hpp>
 
-#include "authorizer/authorizer.hpp"
-
 #include "common/attributes.hpp"
 #include "common/build.hpp"
 #include "common/http.hpp"

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/master/main.cpp
----------------------------------------------------------------------
diff --git a/src/master/main.cpp b/src/master/main.cpp
index 23307e8..3b4a2c1 100644
--- a/src/master/main.cpp
+++ b/src/master/main.cpp
@@ -26,6 +26,8 @@
 
 #include <mesos/mesos.hpp>
 
+#include <mesos/authorizer/authorizer.hpp>
+
 #include <mesos/master/allocator.hpp>
 
 #include <mesos/module/anonymous.hpp>
@@ -46,7 +48,7 @@
 #include <stout/strings.hpp>
 #include <stout/try.hpp>
 
-#include "authorizer/authorizer.hpp"
+#include "authorizer/local/authorizer.hpp"
 
 #include "common/build.hpp"
 #include "common/protobuf_utils.hpp"
@@ -79,6 +81,7 @@ using namespace mesos::internal::log;
 using namespace mesos::internal::master;
 using namespace zookeeper;
 
+using mesos::Authorizer;
 using mesos::MasterInfo;
 
 using mesos::master::allocator::Allocator;
@@ -365,17 +368,23 @@ int main(int argc, char** argv)
 
   Option<Authorizer*> authorizer = None();
   if (flags.acls.isSome()) {
-    Try<Owned<Authorizer>> create = Authorizer::create(flags.acls.get());
+    Try<Authorizer*> local = LocalAuthorizer::create();
 
-    if (create.isError()) {
+    if (local.isError()) {
       EXIT(EXIT_FAILURE)
-        << "Failed to initialize the authorizer: "
-        << create.error() << " (see --acls flag)";
+        << "Failed to instantiate the local authorizer: "
+        << local.error();
     }
 
-    // Now pull out the authorizer but need to make a copy since we
-    // get a 'const &' from 'Try::get'.
-    authorizer = Owned<Authorizer>(create.get()).release();
+    authorizer = local.get();
+
+    Try<Nothing> initialized = authorizer.get()->initialize(flags.acls.get());
+
+    if (initialized.isError()) {
+      EXIT(EXIT_FAILURE)
+        << "Failed to initialize the local authorizer: "
+        << initialized.error() << " (see --acls flag)";
+    }
   }
 
   Option<shared_ptr<RateLimiter>> slaveRemovalLimiter = None();

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/master/master.cpp
----------------------------------------------------------------------
diff --git a/src/master/master.cpp b/src/master/master.cpp
index 83d2f44..c5e6c6f 100644
--- a/src/master/master.cpp
+++ b/src/master/master.cpp
@@ -30,6 +30,8 @@
 
 #include <mesos/authentication/authenticator.hpp>
 
+#include <mesos/authorizer/authorizer.hpp>
+
 #include <mesos/master/allocator.hpp>
 
 #include <mesos/module/authenticator.hpp>
@@ -63,8 +65,6 @@
 
 #include "authentication/cram_md5/authenticator.hpp"
 
-#include "authorizer/authorizer.hpp"
-
 #include "common/build.hpp"
 #include "common/date_utils.hpp"
 #include "common/protobuf_utils.hpp"

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/master/master.hpp
----------------------------------------------------------------------
diff --git a/src/master/master.hpp b/src/master/master.hpp
index b353b8e..1e12f65 100644
--- a/src/master/master.hpp
+++ b/src/master/master.hpp
@@ -78,6 +78,10 @@ class RateLimiter; // Forward declaration.
 }
 
 namespace mesos {
+
+// Forward declarations.
+class Authorizer;
+
 namespace internal {
 
 // Forward declarations.
@@ -85,7 +89,6 @@ namespace registry {
 class Slaves;
 }
 
-class Authorizer;
 class WhitelistWatcher;
 
 namespace master {

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/tests/authorization_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/authorization_tests.cpp b/src/tests/authorization_tests.cpp
index 99bb06c..86dcb6a 100644
--- a/src/tests/authorization_tests.cpp
+++ b/src/tests/authorization_tests.cpp
@@ -18,9 +18,11 @@
 
 #include <gtest/gtest.h>
 
+#include <mesos/authorizer/authorizer.hpp>
+
 #include <process/future.hpp>
 
-#include "authorizer/authorizer.hpp"
+#include "authorizer/local/authorizer.hpp"
 
 #include "tests/mesos.hpp"
 
@@ -43,8 +45,12 @@ TEST_F(AuthorizationTest, AnyPrincipalRunAsUser)
   acl->mutable_users()->add_values("guest");
 
   // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
+  Try<Authorizer*> create = LocalAuthorizer::create();
+  ASSERT_SOME(create);
+  Owned<Authorizer> authorizer(create.get());
+
+  Try<Nothing> initialized = authorizer.get()->initialize(acls);
+  ASSERT_SOME(initialized);
 
   // Principals "foo" and "bar" can run as "guest".
   mesos::ACL::RunTask request;
@@ -70,8 +76,12 @@ TEST_F(AuthorizationTest, NoPrincipalRunAsUser)
   acl->mutable_users()->add_values("root");
 
   // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
+  Try<Authorizer*> create = LocalAuthorizer::create();
+  ASSERT_SOME(create);
+  Owned<Authorizer> authorizer(create.get());
+
+  Try<Nothing> initialized = authorizer.get()->initialize(acls);
+  ASSERT_SOME(initialized);
 
   // Principal "foo" cannot run as "root".
   mesos::ACL::RunTask request;
@@ -90,8 +100,12 @@ TEST_F(AuthorizationTest, PrincipalRunAsAnyUser)
   acl->mutable_users()->set_type(mesos::ACL::Entity::ANY);
 
   // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
+  Try<Authorizer*> create = LocalAuthorizer::create();
+  ASSERT_SOME(create);
+  Owned<Authorizer> authorizer(create.get());
+
+  Try<Nothing> initialized = authorizer.get()->initialize(acls);
+  ASSERT_SOME(initialized);
 
   // Principal "foo" can run as "user1" and "user2".
   mesos::ACL::RunTask request;
@@ -111,8 +125,12 @@ TEST_F(AuthorizationTest, AnyPrincipalRunAsAnyUser)
   acl->mutable_users()->set_type(mesos::ACL::Entity::ANY);
 
   // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
+  Try<Authorizer*> create = LocalAuthorizer::create();
+  ASSERT_SOME(create);
+  Owned<Authorizer> authorizer(create.get());
+
+  Try<Nothing> initialized = authorizer.get()->initialize(acls);
+  ASSERT_SOME(initialized);
 
   // Principals "foo" and "bar" can run as "user1" and "user2".
   mesos::ACL::RunTask request;
@@ -143,8 +161,12 @@ TEST_F(AuthorizationTest, OnlySomePrincipalsRunAsSomeUsers)
   acl2->mutable_users()->add_values("user2");
 
   // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
+  Try<Authorizer*> create = LocalAuthorizer::create();
+  ASSERT_SOME(create);
+  Owned<Authorizer> authorizer(create.get());
+
+  Try<Nothing> initialized = authorizer.get()->initialize(acls);
+  ASSERT_SOME(initialized);
 
   // Principals "foo" and "bar" can run as "user1" and "user2".
   mesos::ACL::RunTask request;
@@ -184,8 +206,12 @@ TEST_F(AuthorizationTest, SomePrincipalOnlySomeUser)
   acl2->mutable_users()->set_type(mesos::ACL::Entity::NONE);
 
   // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
+  Try<Authorizer*> create = LocalAuthorizer::create();
+  ASSERT_SOME(create);
+  Owned<Authorizer> authorizer(create.get());
+
+  Try<Nothing> initialized = authorizer.get()->initialize(acls);
+  ASSERT_SOME(initialized);
 
   // Principal "foo" can run as "user1".
   mesos::ACL::RunTask request;
@@ -218,8 +244,12 @@ TEST_F(AuthorizationTest, PrincipalRunAsSomeUserRestrictive)
   acl->mutable_users()->add_values("user1");
 
   // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
+  Try<Authorizer*> create = LocalAuthorizer::create();
+  ASSERT_SOME(create);
+  Owned<Authorizer> authorizer(create.get());
+
+  Try<Nothing> initialized = authorizer.get()->initialize(acls);
+  ASSERT_SOME(initialized);
 
   // Principal "foo" can run as "user1".
   mesos::ACL::RunTask request;
@@ -250,8 +280,12 @@ TEST_F(AuthorizationTest, AnyPrincipalOfferedRole)
   acl->mutable_roles()->add_values("*");
 
   // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
+  Try<Authorizer*> create = LocalAuthorizer::create();
+  ASSERT_SOME(create);
+  Owned<Authorizer> authorizer(create.get());
+
+  Try<Nothing> initialized = authorizer.get()->initialize(acls);
+  ASSERT_SOME(initialized);
 
   // Principals "foo" and "bar" can be offered "*" role's resources.
   mesos::ACL::RegisterFramework request;
@@ -272,8 +306,12 @@ TEST_F(AuthorizationTest, SomePrincipalsOfferedRole)
   acl->mutable_roles()->add_values("ads");
 
   // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
+  Try<Authorizer*> create = LocalAuthorizer::create();
+  ASSERT_SOME(create);
+  Owned<Authorizer> authorizer(create.get());
+
+  Try<Nothing> initialized = authorizer.get()->initialize(acls);
+  ASSERT_SOME(initialized);
 
   // Principals "foo", "bar" and "baz" (no ACL) can be offered "ads"
   // role's resources.
@@ -302,8 +340,12 @@ TEST_F(AuthorizationTest, PrincipalOfferedRole)
   acl2->mutable_roles()->add_values("analytics");
 
   // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
+  Try<Authorizer*> create = LocalAuthorizer::create();
+  ASSERT_SOME(create);
+  Owned<Authorizer> authorizer(create.get());
+
+  Try<Nothing> initialized = authorizer.get()->initialize(acls);
+  ASSERT_SOME(initialized);
 
   // Principal "foo" can be offered "analytics" role's resources.
   mesos::ACL::RegisterFramework request;
@@ -329,8 +371,12 @@ TEST_F(AuthorizationTest, PrincipalNotOfferedAnyRoleRestrictive)
   acl->mutable_roles()->add_values("analytics");
 
   // Create an Authorizer with the ACLs.
-  Try<Owned<LocalAuthorizer> > authorizer = LocalAuthorizer::create(acls);
-  ASSERT_SOME(authorizer);
+  Try<Authorizer*> create = LocalAuthorizer::create();
+  ASSERT_SOME(create);
+  Owned<Authorizer> authorizer(create.get());
+
+  Try<Nothing> initialized = authorizer.get()->initialize(acls);
+  ASSERT_SOME(initialized);
 
   // Principal "foo" can be offered "analytics" role's resources.
   mesos::ACL::RegisterFramework request;

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/tests/cluster.hpp
----------------------------------------------------------------------
diff --git a/src/tests/cluster.hpp b/src/tests/cluster.hpp
index 422ebd1..b59b750 100644
--- a/src/tests/cluster.hpp
+++ b/src/tests/cluster.hpp
@@ -26,6 +26,8 @@
 
 #include <mesos/mesos.hpp>
 
+#include <mesos/authorizer/authorizer.hpp>
+
 #include <mesos/master/allocator.hpp>
 
 #include <mesos/slave/resource_estimator.hpp>
@@ -49,14 +51,14 @@
 #include <stout/strings.hpp>
 #include <stout/try.hpp>
 
+#include "authorizer/local/authorizer.hpp"
+
 #include "files/files.hpp"
 
 #ifdef __linux__
 #include "linux/cgroups.hpp"
 #endif // __linux__
 
-#include "authorizer/authorizer.hpp"
-
 #include "log/log.hpp"
 
 #include "log/tool/initialize.hpp"
@@ -349,15 +351,22 @@ inline Try<process::PID<master::Master>> Cluster::Masters::start(
   if (authorizer.isSome()) {
     CHECK_NOTNULL(authorizer.get());
   } else if (flags.acls.isSome()) {
-    Try<process::Owned<Authorizer>> create =
-      Authorizer::create(flags.acls.get());
+    Try<Authorizer*> local = LocalAuthorizer::create();
+
+    if (local.isError()) {
+      EXIT(EXIT_FAILURE)
+        << "Failed to instantiate the local authorizer: "
+        << local.error();
+    }
+
+    Try<Nothing> initialized = local.get()->initialize(flags.acls.get());
 
-    if (create.isError()) {
+    if (initialized.isError()) {
       return Error("Failed to initialize the authorizer: " +
-                   create.error() + " (see --acls flag)");
+                   initialized.error() + " (see --acls flag)");
     }
 
-    master.authorizer = process::Owned<Authorizer>(create.get());
+    master.authorizer.reset(local.get());
   }
 
   if (slaveRemovalLimiter.isNone() &&

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/tests/mesos.cpp
----------------------------------------------------------------------
diff --git a/src/tests/mesos.cpp b/src/tests/mesos.cpp
index a2a469e..9bff4a6 100644
--- a/src/tests/mesos.cpp
+++ b/src/tests/mesos.cpp
@@ -19,6 +19,8 @@
 #include <memory>
 #include <string>
 
+#include <mesos/authorizer/authorizer.hpp>
+
 #include <stout/check.hpp>
 #include <stout/foreach.hpp>
 #include <stout/json.hpp>
@@ -28,8 +30,6 @@
 #include <stout/stringify.hpp>
 #include <stout/uuid.hpp>
 
-#include "authorizer/authorizer.hpp"
-
 #ifdef __linux__
 #include "linux/cgroups.hpp"
 #endif

http://git-wip-us.apache.org/repos/asf/mesos/blob/f9a014b6/src/tests/mesos.hpp
----------------------------------------------------------------------
diff --git a/src/tests/mesos.hpp b/src/tests/mesos.hpp
index 8b48614..64987f0 100644
--- a/src/tests/mesos.hpp
+++ b/src/tests/mesos.hpp
@@ -28,6 +28,8 @@
 #include <mesos/executor.hpp>
 #include <mesos/scheduler.hpp>
 
+#include <mesos/authorizer/authorizer.hpp>
+
 #include <mesos/master/allocator.hpp>
 
 #include <mesos/fetcher/fetcher.hpp>
@@ -55,8 +57,6 @@
 #include <stout/try.hpp>
 #include <stout/uuid.hpp>
 
-#include "authorizer/authorizer.hpp"
-
 #include "messages/messages.hpp" // For google::protobuf::Message.
 
 #include "master/detector.hpp"
@@ -973,9 +973,14 @@ public:
 
     EXPECT_CALL(*this, authorize(An<const mesos::ACL::ShutdownFramework&>()))
       .WillRepeatedly(Return(true));
+
+    EXPECT_CALL(*this, initialize(An<const Option<ACLs>&>()))
+      .WillRepeatedly(Return(Nothing()));
   }
 
   MOCK_METHOD1(
+      initialize, Try<Nothing>(const Option<ACLs>& acls));
+  MOCK_METHOD1(
       authorize, process::Future<bool>(const ACL::RegisterFramework& request));
   MOCK_METHOD1(
       authorize, process::Future<bool>(const ACL::RunTask& request));


Mime
View raw message