Added CRAM-MD5 Test Authenticator module.

Introducing the CRAM-MD5 SASL test authenticator module based on the
former sasl/authenticator.

The former sasl/authenticator.hpp still remains as part of libmesos but
now is located at authentication/cram_md5.

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


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

Branch: refs/heads/master
Commit: 880ea7da6b5c4c1ac1fcc05f2ad5f5dfc875b94e
Parents: b51f555
Author: Till Toenshoff <[email protected]>
Authored: Mon Nov 3 14:52:24 2014 -0800
Committer: Adam B <[email protected]>
Committed: Mon Nov 3 14:52:50 2014 -0800

----------------------------------------------------------------------
 src/Makefile.am                               |  20 +++-
 src/authentication/authenticator.hpp          |  57 +++++++++++
 src/authentication/cram_md5/authenticator.hpp | 109 +++++++++++++--------
 src/examples/test_authenticator_module.cpp    |  51 ++++++++++
 src/module/authenticator.hpp                  |  64 ++++++++++++
 src/module/manager.cpp                        |   3 +-
 6 files changed, 258 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/880ea7da/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 21e1e20..9ab3b9c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -248,10 +248,9 @@ nodist_libmesos_no_3rdparty_la_SOURCES =                   
        \
   $(MESSAGES_PROTOS)                                                   \
   $(REGISTRY_PROTOS)
 
+# TODO(tillt): Remove authentication/cram_md5/* which will enable us to
+# lose the immediate cyrus-sasl2 dependency.
 libmesos_no_3rdparty_la_SOURCES =                                      \
-       authentication/cram_md5/authenticatee.hpp                       \
-       authentication/cram_md5/authenticator.hpp                       \
-       authentication/cram_md5/auxprop.hpp                             \
        authentication/cram_md5/auxprop.cpp                             \
        authorizer/authorizer.cpp                                       \
        common/attributes.cpp                                           \
@@ -388,6 +387,10 @@ if WITH_NETWORK_ISOLATOR
 endif
 
 libmesos_no_3rdparty_la_SOURCES +=                                     \
+       authentication/authenticator.hpp                                \
+       authentication/cram_md5/authenticatee.hpp                       \
+       authentication/cram_md5/authenticator.hpp                       \
+       authentication/cram_md5/auxprop.hpp                             \
        authorizer/authorizer.hpp                                       \
        common/attributes.hpp                                           \
        common/build.hpp                                                \
@@ -425,6 +428,7 @@ libmesos_no_3rdparty_la_SOURCES +=                          
        \
        master/registrar.hpp                                            \
        master/sorter.hpp                                               \
        messages/messages.hpp                                           \
+       module/authenticator.hpp                                        \
        module/isolator.hpp                                             \
        module/manager.hpp                                              \
        slave/constants.hpp                                             \
@@ -1175,6 +1179,16 @@ libtestisolator_la_SOURCES = 
examples/test_isolator_module.cpp
 libtestisolator_la_CPPFLAGS = $(MESOS_CPPFLAGS)
 libtestisolator_la_LDFLAGS = -release $(PACKAGE_VERSION) -shared
 
+# Library containing the test CRAM-MD5 authenticator module.
+# TODO(tillt): Add authenticatee module and rename to libauthentication.
+# TODO(tillt): Add cyrus-sasl2 dependency while removing it from libmesos.
+# TODO(tillt): Enable optional building of this module library.
+# TODO(tillt): Make this module library installable. See MESOS-1940.
+lib_LTLIBRARIES += libtestauthenticator.la
+libtestauthenticator_la_SOURCES = examples/test_authenticator_module.cpp
+libtestauthenticator_la_CPPFLAGS = $(MESOS_CPPFLAGS)
+libtestauthenticator_la_LDFLAGS = -release $(PACKAGE_VERSION) -shared
+
 mesos_tests_SOURCES =                          \
   tests/allocator_tests.cpp                    \
   tests/attributes_tests.cpp                   \

http://git-wip-us.apache.org/repos/asf/mesos/blob/880ea7da/src/authentication/authenticator.hpp
----------------------------------------------------------------------
diff --git a/src/authentication/authenticator.hpp 
b/src/authentication/authenticator.hpp
new file mode 100644
index 0000000..2f95db1
--- /dev/null
+++ b/src/authentication/authenticator.hpp
@@ -0,0 +1,57 @@
+/**
+ * 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 __AUTHENTICATOR_HPP__
+#define __AUTHENTICATOR_HPP__
+
+#include <mesos/mesos.hpp>
+
+#include <process/future.hpp>
+#include <process/pid.hpp>
+
+#include <stout/nothing.hpp>
+#include <stout/try.hpp>
+
+namespace mesos {
+namespace internal {
+
+class Authenticator
+{
+public:
+  Authenticator() {}
+  virtual ~Authenticator() {}
+
+  virtual Try<Nothing> initialize(
+      const process::UPID& clientPid,
+      const Option<mesos::Credentials>& credentials) = 0;
+
+  // Returns the principal of the Authenticatee if successfully
+  // authenticated otherwise None or an error. Note that we
+  // distinguish authentication failure (None) from a failed future
+  // in the event the future failed due to a transient error and
+  // authentication can (should) be retried. Discarding the future
+  // will cause the future to fail if it hasn't already completed
+  // since we have already started the authentication procedure and
+  // can't reliably cancel.
+  virtual process::Future<Option<std::string>> authenticate(void) = 0;
+};
+
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __AUTHENTICATOR_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/880ea7da/src/authentication/cram_md5/authenticator.hpp
----------------------------------------------------------------------
diff --git a/src/authentication/cram_md5/authenticator.hpp 
b/src/authentication/cram_md5/authenticator.hpp
index 7953418..601248d 100644
--- a/src/authentication/cram_md5/authenticator.hpp
+++ b/src/authentication/cram_md5/authenticator.hpp
@@ -36,6 +36,8 @@
 
 #include <stout/check.hpp>
 
+#include "authentication/authenticator.hpp"
+
 #include "authentication/cram_md5/auxprop.hpp"
 
 #include "messages/messages.hpp"
@@ -45,14 +47,19 @@ namespace internal {
 namespace cram_md5 {
 
 // Forward declaration.
-class AuthenticatorProcess;
+class CRAMMD5AuthenticatorProcess;
 
 
-class Authenticator
+class CRAMMD5Authenticator : public Authenticator
 {
 public:
-  explicit Authenticator(const process::UPID& pid);
-  ~Authenticator();
+  CRAMMD5Authenticator();
+  virtual ~CRAMMD5Authenticator();
+
+  virtual Try<Nothing> initialize(
+      const process::UPID& clientPid,
+      const Option<Credentials>& credentials);
+
 
   // Returns the principal of the Authenticatee if successfully
   // authenticated otherwise None or an error. Note that we
@@ -62,23 +69,24 @@ public:
   // will cause the future to fail if it hasn't already completed
   // since we have already started the authentication procedure and
   // can't reliably cancel.
-  process::Future<Option<std::string> > authenticate();
+  virtual process::Future<Option<std::string>> authenticate();
 
 private:
-  AuthenticatorProcess* process;
+  CRAMMD5AuthenticatorProcess* process;
 };
 
 
-class AuthenticatorProcess : public ProtobufProcess<AuthenticatorProcess>
+class CRAMMD5AuthenticatorProcess
+  : public ProtobufProcess<CRAMMD5AuthenticatorProcess>
 {
 public:
-  explicit AuthenticatorProcess(const process::UPID& _pid)
-    : ProcessBase(process::ID::generate("authenticator")),
+  explicit CRAMMD5AuthenticatorProcess(const process::UPID& _pid)
+    : ProcessBase(process::ID::generate("crammd5_authenticator")),
       status(READY),
       pid(_pid),
       connection(NULL) {}
 
-  virtual ~AuthenticatorProcess()
+  virtual ~CRAMMD5AuthenticatorProcess()
   {
     if (connection != NULL) {
       sasl_dispose(&connection);
@@ -90,7 +98,7 @@ public:
     discarded(); // Fail the promise.
   }
 
-  process::Future<Option<std::string> > authenticate()
+  process::Future<Option<std::string>> authenticate()
   {
     static process::Once* initialize = new process::Once();
     static bool initialized = false;
@@ -236,12 +244,12 @@ protected:
 
     // Anticipate start and steps messages from the client.
     install<AuthenticationStartMessage>(
-        &AuthenticatorProcess::start,
+        &CRAMMD5AuthenticatorProcess::start,
         &AuthenticationStartMessage::mechanism,
         &AuthenticationStartMessage::data);
 
     install<AuthenticationStepMessage>(
-        &AuthenticatorProcess::step,
+        &CRAMMD5AuthenticatorProcess::step,
         &AuthenticationStepMessage::data);
   }
 
@@ -341,7 +349,7 @@ private:
   }
 
   // Callback for canonicalizing the username (principal). We use it
-  // to record the principal in Authenticator.
+  // to record the principal in CRAMMD5Authenticator.
   static int canonicalize(
       sasl_conn_t* connection,
       void* context,
@@ -425,38 +433,11 @@ private:
 
   sasl_conn_t* connection;
 
-  process::Promise<Option<std::string> > promise;
+  process::Promise<Option<std::string>> promise;
 
   Option<std::string> principal;
 };
 
-
-Authenticator::Authenticator(const process::UPID& pid)
-{
-  process = new AuthenticatorProcess(pid);
-  process::spawn(process);
-}
-
-
-Authenticator::~Authenticator()
-{
-  // TODO(vinod): As a short term fix for the race condition #1 in
-  // MESOS-1866, we inject the 'terminate' event at the end of the
-  // AuthenticatorProcess queue instead of at the front.
-  // The long term fix for this https://reviews.apache.org/r/25945/.
-  process::terminate(process, false);
-
-  process::wait(process);
-  delete process;
-}
-
-
-process::Future<Option<std::string> > Authenticator::authenticate()
-{
-  return process::dispatch(process, &AuthenticatorProcess::authenticate);
-}
-
-
 namespace secrets {
 
 // Loads secrets (principal -> secret) into the in-memory auxiliary
@@ -487,6 +468,50 @@ void load(const Credentials& credentials)
 
 } // namespace secrets {
 
+CRAMMD5Authenticator::CRAMMD5Authenticator() : process(NULL) {}
+
+
+CRAMMD5Authenticator::~CRAMMD5Authenticator()
+{
+  if (process != NULL) {
+    // TODO(vinod): As a short term fix for the race condition #1 in
+    // MESOS-1866, we inject the 'terminate' event at the end of the
+    // CRAMMD5AuthenticatorProcess queue instead of at the front.
+    // The long term fix for this is https://reviews.apache.org/r/25945/.
+    process::terminate(process, false);
+
+    process::wait(process);
+    delete process;
+  }
+}
+
+
+Try<Nothing> CRAMMD5Authenticator::initialize(
+    const process::UPID& pid,
+    const Option<Credentials>& credentials)
+{
+  if (credentials.isSome()) {
+    // Load "registration" credentials into SASL based Authenticator.
+    secrets::load(credentials.get());
+  } else {
+    return Error("Authentication requires credentials");
+  }
+
+  CHECK(process == NULL) << "Authenticator has already been initialized";
+  process = new CRAMMD5AuthenticatorProcess(pid);
+  process::spawn(process);
+
+  return Nothing();
+}
+
+
+process::Future<Option<std::string>> CRAMMD5Authenticator::authenticate(void)
+{
+  CHECK(process != NULL) << "Authenticator has not been initialized";
+  return process::dispatch(
+      process, &CRAMMD5AuthenticatorProcess::authenticate);
+}
+
 } // namespace cram_md5 {
 } // namespace internal {
 } // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/880ea7da/src/examples/test_authenticator_module.cpp
----------------------------------------------------------------------
diff --git a/src/examples/test_authenticator_module.cpp 
b/src/examples/test_authenticator_module.cpp
new file mode 100644
index 0000000..4398d71
--- /dev/null
+++ b/src/examples/test_authenticator_module.cpp
@@ -0,0 +1,51 @@
+/**
+ * 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 <mesos/mesos.hpp>
+#include <mesos/module.hpp>
+
+#include "authentication/authenticator.hpp"
+
+#include "authentication/cram_md5/authenticator.hpp"
+
+#include "module/authenticator.hpp"
+
+using namespace mesos;
+
+using mesos::internal::Authenticator;
+
+static bool compatible()
+{
+  return true;
+}
+
+
+static Authenticator* createCRAMMD5Authenticator(const Parameters& parameters)
+{
+  return new mesos::internal::cram_md5::CRAMMD5Authenticator();
+}
+
+
+mesos::modules::Module<Authenticator> 
org_apache_mesos_TestCRAMMD5Authenticator(
+    MESOS_MODULE_API_VERSION,
+    MESOS_VERSION,
+    "Apache Mesos",
+    "[email protected]",
+    "Test CRAM-MD5 SASL authenticator module.",
+    compatible,
+    createCRAMMD5Authenticator);

http://git-wip-us.apache.org/repos/asf/mesos/blob/880ea7da/src/module/authenticator.hpp
----------------------------------------------------------------------
diff --git a/src/module/authenticator.hpp b/src/module/authenticator.hpp
new file mode 100644
index 0000000..9562338
--- /dev/null
+++ b/src/module/authenticator.hpp
@@ -0,0 +1,64 @@
+/**
+ * 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 __MODULE_AUTHENTICATOR_HPP__
+#define __MODULE_AUTHENTICATOR_HPP__
+
+#include <mesos/module.hpp>
+
+#include "authentication/authenticator.hpp"
+
+namespace mesos {
+namespace modules {
+
+template<>
+inline const char* kind<mesos::internal::Authenticator>()
+{
+  return "Authenticator";
+}
+
+
+template <>
+struct Module<mesos::internal::Authenticator> : ModuleBase
+{
+  Module(
+      const char* _moduleApiVersion,
+      const char* _mesosVersion,
+      const char* _authorName,
+      const char* _authorEmail,
+      const char* _description,
+      bool (*_compatible)(),
+      mesos::internal::Authenticator* (*_create)(const Parameters& parameters))
+    : ModuleBase(
+        _moduleApiVersion,
+        _mesosVersion,
+        mesos::modules::kind<mesos::internal::Authenticator>(),
+        _authorName,
+        _authorEmail,
+        _description,
+        _compatible),
+      create(_create)
+  { }
+
+  mesos::internal::Authenticator* (*create)(const Parameters& parameters);
+};
+
+} // namespace modules {
+} // namespace mesos {
+
+#endif // __MODULE_AUTHENTICATOR_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/880ea7da/src/module/manager.cpp
----------------------------------------------------------------------
diff --git a/src/module/manager.cpp b/src/module/manager.cpp
index 7a6c884..3062c41 100644
--- a/src/module/manager.cpp
+++ b/src/module/manager.cpp
@@ -57,8 +57,9 @@ void ModuleManager::initialize()
   // current change.  Typically that should be the version currently
   // under development.
 
-  kindToVersion["TestModule"] = MESOS_VERSION;
+  kindToVersion["Authenticator"] = MESOS_VERSION;
   kindToVersion["Isolator"] = MESOS_VERSION;
+  kindToVersion["TestModule"] = MESOS_VERSION;
 
   // What happens then when Mesos is built with a certain version,
   // 'kindToVersion' states a certain other minimum version, and a

Reply via email to