Allowed tests to authorize libprocess HTTP endpoints.

The test cluster initialization code was altered
to enable authorization of libprocess-level HTTP
endpoints when a master or agent is launched
with authorization enabled.

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


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

Branch: refs/heads/master
Commit: d5e1a47dbb5db4af372a079d8cd287392ebe30fa
Parents: 12b05e8
Author: Greg Mann <[email protected]>
Authored: Wed May 11 22:45:43 2016 -0400
Committer: Kapil Arya <[email protected]>
Committed: Thu May 12 01:50:20 2016 -0400

----------------------------------------------------------------------
 src/tests/cluster.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++++
 src/tests/cluster.hpp | 14 +++++++++++
 2 files changed, 77 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/d5e1a47d/src/tests/cluster.cpp
----------------------------------------------------------------------
diff --git a/src/tests/cluster.cpp b/src/tests/cluster.cpp
index db72628..c03e053 100644
--- a/src/tests/cluster.cpp
+++ b/src/tests/cluster.cpp
@@ -39,6 +39,7 @@
 #include <process/future.hpp>
 #include <process/gmock.hpp>
 #include <process/gtest.hpp>
+#include <process/http.hpp>
 #include <process/id.hpp>
 #include <process/limiter.hpp>
 #include <process/owned.hpp>
@@ -61,6 +62,8 @@
 
 #include "authorizer/local/authorizer.hpp"
 
+#include "common/http.hpp"
+
 #include "files/files.hpp"
 
 #include "master/constants.hpp"
@@ -125,6 +128,10 @@ Try<process::Owned<Master>> Master::start(
 
   // If the authorizer is not provided, create a default one.
   if (authorizer.isNone()) {
+    // Indicates whether or not the caller explicitly specified the
+    // authorization configuration for this master.
+    bool authorizationSpecified = true;
+
     std::vector<std::string> authorizerNames =
       strings::split(flags.authorizers, ",");
 
@@ -149,6 +156,9 @@ Try<process::Owned<Master>> Master::start(
         LOG(INFO) << "Creating default '" << authorizerName << "' authorizer";
 
         authorizer = Authorizer::create(flags.acls.get());
+        CHECK_SOME(authorizer);
+      } else {
+        authorizationSpecified = false;
       }
     }
 
@@ -158,7 +168,16 @@ Try<process::Owned<Master>> Master::start(
           authorizer.error());
     } else if (authorizer.isSome()) {
       master->authorizer.reset(authorizer.get());
+
+      if (authorizationSpecified) {
+        // Authorization config was explicitly provided, so set authorization
+        // callbacks in libprocess.
+        master->setAuthorizationCallbacks(authorizer.get());
+      }
     }
+  } else {
+    // An authorizer was provided, so set authorization callbacks in 
libprocess.
+    master->setAuthorizationCallbacks(authorizer.get());
   }
 
   // Create the appropriate master contender/detector.
@@ -317,6 +336,11 @@ Try<process::Owned<Master>> Master::start(
 
 Master::~Master()
 {
+  // Remove any libprocess authorization callbacks that were installed.
+  if (authorizationCallbacksSet) {
+    process::http::authorization::unsetCallbacks();
+  }
+
   // NOTE: Authenticators' lifetimes are tied to libprocess's lifetime.
   // This means that multiple masters in tests are not supported.
   process::http::authentication::unsetAuthenticator(
@@ -344,6 +368,15 @@ MasterInfo Master::getMasterInfo()
 }
 
 
+void Master::setAuthorizationCallbacks(Authorizer* authorizer)
+{
+  process::http::authorization::setCallbacks(
+      mesos::createAuthorizationCallbacks(authorizer));
+
+  authorizationCallbacksSet = true;
+}
+
+
 Try<process::Owned<Slave>> Slave::start(
     MasterDetector* detector,
     const slave::Flags& flags,
@@ -384,6 +417,10 @@ Try<process::Owned<Slave>> Slave::start(
 
   // If the authorizer is not provided, create a default one.
   if (providedAuthorizer.isNone()) {
+    // Indicates whether or not the caller explicitly specified the
+    // authorization configuration for this agent.
+    bool authorizationSpecified = true;
+
     std::string authorizerName = flags.authorizer;
 
     Result<Authorizer*> createdAuthorizer((None()));
@@ -398,6 +435,9 @@ Try<process::Owned<Slave>> Slave::start(
         LOG(INFO) << "Creating default '" << authorizerName << "' authorizer";
 
         createdAuthorizer = Authorizer::create(flags.acls.get());
+      } else {
+        // Neither a non-default authorizer nor a set of ACLs were specified.
+        authorizationSpecified = false;
       }
     }
 
@@ -407,7 +447,16 @@ Try<process::Owned<Slave>> Slave::start(
     } else if (createdAuthorizer.isSome()) {
       slave->authorizer.reset(createdAuthorizer.get());
       authorizer = createdAuthorizer.get();
+
+      if (authorizationSpecified) {
+        // Authorization config was explicitly provided, so set authorization
+        // callbacks in libprocess.
+        slave->setAuthorizationCallbacks(authorizer.get());
+      }
     }
+  } else {
+    // An authorizer was provided, so set authorization callbacks in 
libprocess.
+    slave->setAuthorizationCallbacks(providedAuthorizer.get());
   }
 
   // If the garbage collector is not provided, create a default one.
@@ -467,6 +516,11 @@ Try<process::Owned<Slave>> Slave::start(
 
 Slave::~Slave()
 {
+  // Remove any libprocess authorization callbacks that were installed.
+  if (authorizationCallbacksSet) {
+    process::http::authorization::unsetCallbacks();
+  }
+
   // If either `shutdown()` or `terminate()` were called already,
   // skip the below container cleanup logic.  Additionally, we can skip
   // termination, as the shutdown/terminate will do this too.
@@ -511,6 +565,15 @@ Slave::~Slave()
 }
 
 
+void Slave::setAuthorizationCallbacks(Authorizer* authorizer)
+{
+  process::http::authorization::setCallbacks(
+      mesos::createAuthorizationCallbacks(authorizer));
+
+  authorizationCallbacksSet = true;
+}
+
+
 void Slave::shutdown()
 {
   cleanUpContainersInDestructor = false;

http://git-wip-us.apache.org/repos/asf/mesos/blob/d5e1a47d/src/tests/cluster.hpp
----------------------------------------------------------------------
diff --git a/src/tests/cluster.hpp b/src/tests/cluster.hpp
index 60ab3f7..c93f052 100644
--- a/src/tests/cluster.hpp
+++ b/src/tests/cluster.hpp
@@ -99,6 +99,9 @@ public:
   // The underlying master process.
   process::PID<master::Master> pid;
 
+  // Sets authorization callbacks in libprocess.
+  void setAuthorizationCallbacks(Authorizer* authorizer);
+
 private:
   Master() : files(master::DEFAULT_HTTP_AUTHENTICATION_REALM) {};
 
@@ -122,6 +125,10 @@ private:
 
   Option<std::shared_ptr<process::RateLimiter>> slaveRemovalLimiter;
 
+  // Indicates whether or not authorization callbacks were set when this master
+  // was constructed.
+  bool authorizationCallbacksSet;
+
   // The underlying master object.
   process::Owned<master::Master> master;
 };
@@ -166,6 +173,9 @@ public:
   // The underlying slave process.
   process::PID<slave::Slave> pid;
 
+  // Sets authorization callbacks in libprocess.
+  void setAuthorizationCallbacks(Authorizer* authorizer);
+
 private:
   Slave() : files(slave::DEFAULT_HTTP_AUTHENTICATION_REALM) {};
 
@@ -203,6 +213,10 @@ private:
   process::Owned<mesos::slave::ResourceEstimator> resourceEstimator;
   process::Owned<slave::StatusUpdateManager> statusUpdateManager;
 
+  // Indicates whether or not authorization callbacks were set when this agent
+  // was constructed.
+  bool authorizationCallbacksSet;
+
   // The underlying slave object.
   process::Owned<slave::Slave> slave;
 };

Reply via email to