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
