Repository: mesos Updated Branches: refs/heads/master 4e2eddb6f -> 1bb7ed289
Allowed the agent to require executor authentication. This patch updates the agent initialization code to make use of the new `--authenticate_http_executors` flag. When the flag is set, authentication is required on the executor realm and the JWT authenticator is loaded. Review: https://reviews.apache.org/r/57671/ Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/1bb7ed28 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/1bb7ed28 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/1bb7ed28 Branch: refs/heads/master Commit: 1bb7ed28977d9b03c6a9162e8d8d10c7420a47f9 Parents: 3e62a13 Author: Greg Mann <[email protected]> Authored: Fri Mar 24 10:01:06 2017 -0700 Committer: Anand Mazumdar <[email protected]> Committed: Fri Mar 24 10:01:33 2017 -0700 ---------------------------------------------------------------------- src/common/http.cpp | 39 ++++++++++++++++++++++++++++++- src/common/http.hpp | 7 +++++- src/slave/flags.cpp | 3 +-- src/slave/flags.hpp | 2 +- src/slave/slave.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++---- src/slave/slave.hpp | 6 +++++ 6 files changed, 108 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/1bb7ed28/src/common/http.cpp ---------------------------------------------------------------------- diff --git a/src/common/http.cpp b/src/common/http.cpp index 942761e..7afbc61 100644 --- a/src/common/http.cpp +++ b/src/common/http.cpp @@ -30,6 +30,7 @@ #include <mesos/authorizer/authorizer.hpp> #include <mesos/module/http_authenticator.hpp> +#include <process/authenticator.hpp> #include <process/dispatch.hpp> #include <process/future.hpp> #include <process/http.hpp> @@ -59,6 +60,9 @@ using process::Failure; using process::Owned; using process::http::authentication::Authenticator; +#ifdef USE_SSL_SOCKET +using process::http::authentication::JWTAuthenticator; +#endif // USE_SSL_SOCKET using process::http::authentication::Principal; using process::http::authorization::AuthorizationCallbacks; @@ -962,6 +966,28 @@ Result<Authenticator*> createBasicAuthenticator( } +#ifdef USE_SSL_SOCKET +Result<Authenticator*> createJWTAuthenticator( + const string& realm, + const string& authenticatorName, + const Option<string>& secretKey) +{ + if (secretKey.isNone()) { + return Error( + "No secret key provided for the default '" + + string(internal::DEFAULT_JWT_HTTP_AUTHENTICATOR) + + "' HTTP authenticator for realm '" + realm + "'"); + } + + LOG(INFO) << "Creating default '" + << internal::DEFAULT_JWT_HTTP_AUTHENTICATOR + << "' HTTP authenticator for realm '" << realm << "'"; + + return new JWTAuthenticator(realm, secretKey.get()); +} +#endif // USE_SSL_SOCKET + + Result<Authenticator*> createCustomAuthenticator( const string& realm, const string& authenticatorName) @@ -986,7 +1012,8 @@ Result<Authenticator*> createCustomAuthenticator( Try<Nothing> initializeHttpAuthenticators( const string& realm, const vector<string>& authenticatorNames, - const Option<Credentials>& credentials) + const Option<Credentials>& credentials, + const Option<string>& secretKey) { if (authenticatorNames.empty()) { return Error( @@ -1000,6 +1027,12 @@ Try<Nothing> initializeHttpAuthenticators( if (authenticatorNames[0] == internal::DEFAULT_BASIC_HTTP_AUTHENTICATOR) { authenticator_ = createBasicAuthenticator(realm, authenticatorNames[0], credentials); +#ifdef USE_SSL_SOCKET + } else if ( + authenticatorNames[0] == internal::DEFAULT_JWT_HTTP_AUTHENTICATOR) { + authenticator_ = + createJWTAuthenticator(realm, authenticatorNames[0], secretKey); +#endif // USE_SSL_SOCKET } else { authenticator_ = createCustomAuthenticator(realm, authenticatorNames[0]); } @@ -1020,6 +1053,10 @@ Try<Nothing> initializeHttpAuthenticators( Result<Authenticator*> authenticator_ = None(); if (name == internal::DEFAULT_BASIC_HTTP_AUTHENTICATOR) { authenticator_ = createBasicAuthenticator(realm, name, credentials); +#ifdef USE_SSL_SOCKET + } else if (name == internal::DEFAULT_JWT_HTTP_AUTHENTICATOR) { + authenticator_ = createJWTAuthenticator(realm, name, secretKey); +#endif // USE_SSL_SOCKET } else { authenticator_ = createCustomAuthenticator(realm, name); } http://git-wip-us.apache.org/repos/asf/mesos/blob/1bb7ed28/src/common/http.hpp ---------------------------------------------------------------------- diff --git a/src/common/http.hpp b/src/common/http.hpp index 23984b3..9a10312 100644 --- a/src/common/http.hpp +++ b/src/common/http.hpp @@ -46,6 +46,9 @@ namespace internal { // Name of the default, basic authenticator. constexpr char DEFAULT_BASIC_HTTP_AUTHENTICATOR[] = "basic"; +// Name of the default, JWT authenticator. +constexpr char DEFAULT_JWT_HTTP_AUTHENTICATOR[] = "jwt"; + extern hashset<std::string> AUTHORIZABLE_ENDPOINTS; @@ -206,6 +209,7 @@ bool approveViewRole( * @param realm name of the realm. * @param authenticatorNames a vector of authenticator names. * @param credentials optional credentials for BasicAuthenticator only. + * @param secretKey optional secret key for the JWTAuthenticator only. * @return nothing if authenticators are initialized and registered to * libprocess successfully, or error if authenticators cannot * be initialized. @@ -213,7 +217,8 @@ bool approveViewRole( Try<Nothing> initializeHttpAuthenticators( const std::string& realm, const std::vector<std::string>& httpAuthenticatorNames, - const Option<Credentials>& credentials); + const Option<Credentials>& credentials = None(), + const Option<std::string>& secretKey = None()); } // namespace mesos { http://git-wip-us.apache.org/repos/asf/mesos/blob/1bb7ed28/src/slave/flags.cpp ---------------------------------------------------------------------- diff --git a/src/slave/flags.cpp b/src/slave/flags.cpp index 8d2e2e3..7688153 100644 --- a/src/slave/flags.cpp +++ b/src/slave/flags.cpp @@ -877,8 +877,7 @@ mesos::internal::slave::Flags::Flags() "HTTP authenticator implementation to use when handling requests to\n" "authenticated endpoints. Use the default\n" "`" + string(DEFAULT_BASIC_HTTP_AUTHENTICATOR) + "`, or load an\n" - "alternate HTTP authenticator module using `--modules`.", - DEFAULT_BASIC_HTTP_AUTHENTICATOR); + "alternate HTTP authenticator module using `--modules`."); add(&Flags::authenticate_http_readwrite, "authenticate_http_readwrite", http://git-wip-us.apache.org/repos/asf/mesos/blob/1bb7ed28/src/slave/flags.hpp ---------------------------------------------------------------------- diff --git a/src/slave/flags.hpp b/src/slave/flags.hpp index 2d982f9..224fac1 100644 --- a/src/slave/flags.hpp +++ b/src/slave/flags.hpp @@ -144,7 +144,7 @@ public: Option<std::string> modulesDir; std::string authenticatee; std::string authorizer; - std::string http_authenticators; + Option<std::string> http_authenticators; bool authenticate_http_readonly; bool authenticate_http_readwrite; #ifdef USE_SSL_SOCKET http://git-wip-us.apache.org/repos/asf/mesos/blob/1bb7ed28/src/slave/slave.cpp ---------------------------------------------------------------------- diff --git a/src/slave/slave.cpp b/src/slave/slave.cpp index 3acb29d..d68d6b9 100644 --- a/src/slave/slave.cpp +++ b/src/slave/slave.cpp @@ -31,6 +31,8 @@ #include <mesos/type_utils.hpp> +#include <mesos/authentication/secret_generator.hpp> + #include <mesos/module/authenticatee.hpp> #include <process/async.hpp> @@ -63,6 +65,10 @@ #include "authentication/cram_md5/authenticatee.hpp" +#ifdef USE_SSL_SOCKET +#include "authentication/executor/jwt_secret_generator.hpp" +#endif // USE_SSL_SOCKET + #include "common/build.hpp" #include "common/protobuf_utils.hpp" #include "common/resources_utils.hpp" @@ -98,6 +104,12 @@ using google::protobuf::RepeatedPtrField; +using mesos::SecretGenerator; + +#ifdef USE_SSL_SOCKET +using mesos::authentication::executor::JWTSecretGenerator; +#endif // USE_SSL_SOCKET + using mesos::authorization::createSubject; using mesos::executor::Call; @@ -260,11 +272,50 @@ void Slave::initialize() httpCredentials = credentials.get(); } + string httpAuthenticators; + if (flags.http_authenticators.isSome()) { + httpAuthenticators = flags.http_authenticators.get(); +#ifdef USE_SSL_SOCKET + } else if (flags.authenticate_http_executors) { + httpAuthenticators = + string(DEFAULT_BASIC_HTTP_AUTHENTICATOR) + "," + + string(DEFAULT_JWT_HTTP_AUTHENTICATOR); +#endif // USE_SSL_SOCKET + } else { + httpAuthenticators = DEFAULT_BASIC_HTTP_AUTHENTICATOR; + } + + Option<string> secretKey; +#ifdef USE_SSL_SOCKET + if (flags.executor_secret_key.isSome()) { + secretKey = flags.executor_secret_key.get(); + secretGenerator.reset(new JWTSecretGenerator(secretKey.get())); + } + + if (flags.authenticate_http_executors) { + if (flags.executor_secret_key.isNone()) { + EXIT(EXIT_FAILURE) << "--executor_secret_key must be specified when " + << "--authenticate_http_executors is set to true"; + } + + Try<Nothing> result = initializeHttpAuthenticators( + EXECUTOR_HTTP_AUTHENTICATION_REALM, + strings::split(httpAuthenticators, ","), + httpCredentials, + secretKey); + + if (result.isError()) { + EXIT(EXIT_FAILURE) << result.error(); + } + } +#endif // USE_SSL_SOCKET + if (flags.authenticate_http_readonly) { Try<Nothing> result = initializeHttpAuthenticators( READONLY_HTTP_AUTHENTICATION_REALM, - strings::split(flags.http_authenticators, ","), - httpCredentials); + strings::split(httpAuthenticators, ","), + httpCredentials, + secretKey); if (result.isError()) { EXIT(EXIT_FAILURE) << result.error(); @@ -274,8 +325,9 @@ void Slave::initialize() if (flags.authenticate_http_readwrite) { Try<Nothing> result = initializeHttpAuthenticators( READWRITE_HTTP_AUTHENTICATION_REALM, - strings::split(flags.http_authenticators, ","), - httpCredentials); + strings::split(httpAuthenticators, ","), + httpCredentials, + secretKey); if (result.isError()) { EXIT(EXIT_FAILURE) << result.error(); http://git-wip-us.apache.org/repos/asf/mesos/blob/1bb7ed28/src/slave/slave.hpp ---------------------------------------------------------------------- diff --git a/src/slave/slave.hpp b/src/slave/slave.hpp index 7ab646e..e06525b 100644 --- a/src/slave/slave.hpp +++ b/src/slave/slave.hpp @@ -32,6 +32,8 @@ #include <mesos/agent/agent.hpp> +#include <mesos/authentication/secret_generator.hpp> + #include <mesos/executor/executor.hpp> #include <mesos/master/detector.hpp> @@ -884,6 +886,10 @@ private: // The most recent estimate of the total amount of oversubscribed // (allocated and oversubscribable) resources. Option<Resources> oversubscribedResources; + +protected: + // Made protected for testing purposes. + process::Owned<mesos::SecretGenerator> secretGenerator; };
