You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2017/11/30 00:04:14 UTC

[03/13] mesos git commit: Generated authentication tokens for local resource providers.

Generated authentication tokens for local resource providers.

`LocalResourceProviderDaemon` now uses `Slave::secretGenerater` to
generate an authentication token for each local resource provider. The
authentication token can then be used to call the V1 agent API. In order
to generate the tokens, `LocalResourceProviderDaemon::load()` is now an
asynchronous function.

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


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

Branch: refs/heads/master
Commit: 9bee2c300e2443e875a26858453563cedf438234
Parents: 957b0c0
Author: Chun-Hung Hsiao <ch...@mesosphere.io>
Authored: Wed Nov 29 15:30:33 2017 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Wed Nov 29 15:30:33 2017 -0800

----------------------------------------------------------------------
 src/resource_provider/daemon.cpp           | 91 +++++++++++++++++++++----
 src/resource_provider/daemon.hpp           |  8 ++-
 src/resource_provider/local.cpp            |  5 +-
 src/resource_provider/local.hpp            |  3 +-
 src/resource_provider/storage/provider.cpp | 21 +++---
 src/resource_provider/storage/provider.hpp |  6 +-
 src/slave/slave.cpp                        | 15 ++--
 7 files changed, 115 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/9bee2c30/src/resource_provider/daemon.cpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/daemon.cpp b/src/resource_provider/daemon.cpp
index 80b5c71..339216b 100644
--- a/src/resource_provider/daemon.cpp
+++ b/src/resource_provider/daemon.cpp
@@ -22,6 +22,7 @@
 
 #include <mesos/type_utils.hpp>
 
+#include <process/defer.hpp>
 #include <process/dispatch.hpp>
 #include <process/id.hpp>
 #include <process/process.hpp>
@@ -36,6 +37,8 @@
 #include <stout/protobuf.hpp>
 #include <stout/try.hpp>
 
+#include "common/validation.hpp"
+
 #include "resource_provider/local.hpp"
 
 namespace http = process::http;
@@ -49,11 +52,14 @@ using process::Owned;
 using process::Process;
 using process::ProcessBase;
 
+using process::defer;
 using process::dispatch;
 using process::spawn;
 using process::terminate;
 using process::wait;
 
+using process::http::authentication::Principal;
+
 namespace mesos {
 namespace internal {
 
@@ -64,11 +70,13 @@ public:
   LocalResourceProviderDaemonProcess(
       const http::URL& _url,
       const string& _workDir,
-      const Option<string>& _configDir)
+      const Option<string>& _configDir,
+      SecretGenerator* _secretGenerator)
     : ProcessBase(process::ID::generate("local-resource-provider-daemon")),
       url(_url),
       workDir(_workDir),
-      configDir(_configDir) {}
+      configDir(_configDir),
+      secretGenerator(_secretGenerator) {}
 
   LocalResourceProviderDaemonProcess(
       const LocalResourceProviderDaemonProcess& other) = delete;
@@ -95,9 +103,12 @@ private:
 
   Future<Nothing> launch(const string& type, const string& name);
 
+  Future<Option<string>> generateAuthToken(const ResourceProviderInfo& info);
+
   const http::URL url;
   const string workDir;
   const Option<string> configDir;
+  SecretGenerator* const secretGenerator;
 
   Option<SlaveID> slaveId;
   hashmap<string, hashmap<string, ProviderData>> providers;
@@ -203,26 +214,69 @@ Future<Nothing> LocalResourceProviderDaemonProcess::launch(
   CHECK_SOME(slaveId);
   CHECK(providers[type].contains(name));
 
-  ProviderData& data = providers[type].at(name);
+  return generateAuthToken(providers[type].at(name).info)
+    .then(defer(self(), [=](
+        const Option<string>& authToken) -> Future<Nothing> {
+      ProviderData& data = providers[type].at(name);
+
+      Try<Owned<LocalResourceProvider>> provider =
+        LocalResourceProvider::create(url, data.info, authToken);
+
+      if (provider.isError()) {
+        return Failure(
+            "Failed to create resource provider with type '" + type +
+            "' and name '" + name + "': " + provider.error());
+      }
+
+      data.provider = provider.get();
+
+      return Nothing();
+    }));
+}
 
-  Try<Owned<LocalResourceProvider>> provider =
-    LocalResourceProvider::create(url, data.info);
 
-  if (provider.isError()) {
+// Generates a secret for local resource provider authentication if needed.
+Future<Option<string>> LocalResourceProviderDaemonProcess::generateAuthToken(
+    const ResourceProviderInfo& info)
+{
+  if (secretGenerator == nullptr) {
+    return None();
+  }
+
+  Try<Principal> principal = LocalResourceProvider::principal(info);
+
+  if (principal.isError()) {
     return Failure(
-        "Failed to create resource provider with type '" + type +
-        "' and name '" + name + "': " + provider.error());
+        "Failed to generate resource provider principal with type '" +
+        info.type() + "' and name '" + info.name() + "': " +
+        principal.error());
   }
 
-  data.provider = provider.get();
+  return secretGenerator->generate(principal.get())
+    .then(defer(self(), [](const Secret& secret) -> Future<Option<string>> {
+      Option<Error> error = common::validation::validateSecret(secret);
 
-  return Nothing();
+      if (error.isSome()) {
+        return Failure(
+            "Failed to validate generated secret: " + error->message);
+      } else if (secret.type() != Secret::VALUE) {
+        return Failure(
+            "Expecting generated secret to be of VALUE type instead of " +
+            stringify(secret.type()) + " type; " +
+            "only VALUE type secrets are supported at this time");
+      }
+
+      CHECK(secret.has_value());
+
+      return secret.value().data();
+    }));
 }
 
 
 Try<Owned<LocalResourceProviderDaemon>> LocalResourceProviderDaemon::create(
     const http::URL& url,
-    const slave::Flags& flags)
+    const slave::Flags& flags,
+    SecretGenerator* secretGenerator)
 {
   // We require that the config directory exists to create a daemon.
   Option<string> configDir = flags.resource_provider_config_dir;
@@ -230,15 +284,24 @@ Try<Owned<LocalResourceProviderDaemon>> LocalResourceProviderDaemon::create(
     return Error("Config directory '" + configDir.get() + "' does not exist");
   }
 
-  return new LocalResourceProviderDaemon(url, flags.work_dir, configDir);
+  return new LocalResourceProviderDaemon(
+      url,
+      flags.work_dir,
+      configDir,
+      secretGenerator);
 }
 
 
 LocalResourceProviderDaemon::LocalResourceProviderDaemon(
     const http::URL& url,
     const string& workDir,
-    const Option<string>& configDir)
-  : process(new LocalResourceProviderDaemonProcess(url, workDir, configDir))
+    const Option<string>& configDir,
+    SecretGenerator* secretGenerator)
+  : process(new LocalResourceProviderDaemonProcess(
+        url,
+        workDir,
+        configDir,
+        secretGenerator))
 {
   spawn(CHECK_NOTNULL(process.get()));
 }

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bee2c30/src/resource_provider/daemon.hpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/daemon.hpp b/src/resource_provider/daemon.hpp
index 8668cd1..14bc41f 100644
--- a/src/resource_provider/daemon.hpp
+++ b/src/resource_provider/daemon.hpp
@@ -21,6 +21,8 @@
 
 #include <mesos/mesos.hpp>
 
+#include <mesos/authentication/secret_generator.hpp>
+
 #include <process/http.hpp>
 #include <process/owned.hpp>
 
@@ -44,7 +46,8 @@ class LocalResourceProviderDaemon
 public:
   static Try<process::Owned<LocalResourceProviderDaemon>> create(
       const process::http::URL& url,
-      const slave::Flags& flags);
+      const slave::Flags& flags,
+      SecretGenerator* secretGenerator);
 
   ~LocalResourceProviderDaemon();
 
@@ -60,7 +63,8 @@ private:
   LocalResourceProviderDaemon(
       const process::http::URL& url,
       const std::string& workDir,
-      const Option<std::string>& configDir);
+      const Option<std::string>& configDir,
+      SecretGenerator* secretGenerator);
 
   process::Owned<LocalResourceProviderDaemonProcess> process;
 };

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bee2c30/src/resource_provider/local.cpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/local.cpp b/src/resource_provider/local.cpp
index ff9819e..42b6b62 100644
--- a/src/resource_provider/local.cpp
+++ b/src/resource_provider/local.cpp
@@ -34,7 +34,8 @@ namespace internal {
 
 Try<Owned<LocalResourceProvider>> LocalResourceProvider::create(
     const http::URL& url,
-    const ResourceProviderInfo& info)
+    const ResourceProviderInfo& info,
+    const Option<string>& authToken)
 {
   // TODO(jieyu): Document the built-in local resource providers.
   const hashmap<string, lambda::function<decltype(create)>> creators = {
@@ -44,7 +45,7 @@ Try<Owned<LocalResourceProvider>> LocalResourceProvider::create(
   };
 
   if (creators.contains(info.type())) {
-    return creators.at(info.type())(url, info);
+    return creators.at(info.type())(url, info, authToken);
   }
 
   return Error("Unknown local resource provider type '" + info.type() + "'");

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bee2c30/src/resource_provider/local.hpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/local.hpp b/src/resource_provider/local.hpp
index 40c8f98..d1dfc90 100644
--- a/src/resource_provider/local.hpp
+++ b/src/resource_provider/local.hpp
@@ -33,7 +33,8 @@ class LocalResourceProvider
 public:
   static Try<process::Owned<LocalResourceProvider>> create(
       const process::http::URL& url,
-      const ResourceProviderInfo& info);
+      const ResourceProviderInfo& info,
+      const Option<std::string>& authToken);
 
   static Try<process::http::authentication::Principal> principal(
       const ResourceProviderInfo& info);

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bee2c30/src/resource_provider/storage/provider.cpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/storage/provider.cpp b/src/resource_provider/storage/provider.cpp
index 6817df5..14d824c 100644
--- a/src/resource_provider/storage/provider.cpp
+++ b/src/resource_provider/storage/provider.cpp
@@ -94,12 +94,14 @@ class StorageLocalResourceProviderProcess
 {
 public:
   explicit StorageLocalResourceProviderProcess(
-      const process::http::URL& _url,
-      const ResourceProviderInfo& _info)
+      const http::URL& _url,
+      const ResourceProviderInfo& _info,
+      const Option<string>& _authToken)
     : ProcessBase(process::ID::generate("storage-local-resource-provider")),
       url(_url),
       contentType(ContentType::PROTOBUF),
-      info(_info) {}
+      info(_info),
+      authToken(_authToken) {}
 
   StorageLocalResourceProviderProcess(
       const StorageLocalResourceProviderProcess& other) = delete;
@@ -118,6 +120,7 @@ private:
   const ContentType contentType;
   ResourceProviderInfo info;
   Owned<v1::resource_provider::Driver> driver;
+  Option<string> authToken;
 };
 
 
@@ -165,7 +168,7 @@ void StorageLocalResourceProviderProcess::initialize()
       defer(self(), &Self::disconnected),
       defer(self(), [this](queue<v1::resource_provider::Event> events) {
         while(!events.empty()) {
-        const v1::resource_provider::Event& event = events.front();
+          const v1::resource_provider::Event& event = events.front();
           received(devolve(event));
           events.pop();
         }
@@ -176,7 +179,8 @@ void StorageLocalResourceProviderProcess::initialize()
 
 Try<Owned<LocalResourceProvider>> StorageLocalResourceProvider::create(
     const process::http::URL& url,
-    const ResourceProviderInfo& info)
+    const ResourceProviderInfo& info,
+    const Option<string>& authToken)
 {
   // Verify that the name follows Java package naming convention.
   // TODO(chhsiao): We should move this check to a validation function
@@ -188,7 +192,7 @@ Try<Owned<LocalResourceProvider>> StorageLocalResourceProvider::create(
   }
 
   return Owned<LocalResourceProvider>(
-      new StorageLocalResourceProvider(url, info));
+      new StorageLocalResourceProvider(url, info, authToken));
 }
 
 
@@ -203,8 +207,9 @@ Try<Principal> StorageLocalResourceProvider::principal(
 
 StorageLocalResourceProvider::StorageLocalResourceProvider(
     const process::http::URL& url,
-    const ResourceProviderInfo& info)
-  : process(new StorageLocalResourceProviderProcess(url, info))
+    const ResourceProviderInfo& info,
+    const Option<string>& authToken)
+  : process(new StorageLocalResourceProviderProcess(url, info, authToken))
 {
   spawn(CHECK_NOTNULL(process.get()));
 }

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bee2c30/src/resource_provider/storage/provider.hpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/storage/provider.hpp b/src/resource_provider/storage/provider.hpp
index b61b41b..720b061 100644
--- a/src/resource_provider/storage/provider.hpp
+++ b/src/resource_provider/storage/provider.hpp
@@ -38,7 +38,8 @@ class StorageLocalResourceProvider : public LocalResourceProvider
 public:
   static Try<process::Owned<LocalResourceProvider>> create(
       const process::http::URL& url,
-      const mesos::ResourceProviderInfo& info);
+      const mesos::ResourceProviderInfo& info,
+      const Option<std::string>& authToken);
 
   static Try<process::http::authentication::Principal> principal(
       const mesos::ResourceProviderInfo& info);
@@ -54,7 +55,8 @@ public:
 private:
   explicit StorageLocalResourceProvider(
       const process::http::URL& url,
-      const mesos::ResourceProviderInfo& info);
+      const mesos::ResourceProviderInfo& info,
+      const Option<std::string>& authToken);
 
   process::Owned<StorageLocalResourceProviderProcess> process;
 };

http://git-wip-us.apache.org/repos/asf/mesos/blob/9bee2c30/src/slave/slave.cpp
----------------------------------------------------------------------
diff --git a/src/slave/slave.cpp b/src/slave/slave.cpp
index e156683..554a2da 100644
--- a/src/slave/slave.cpp
+++ b/src/slave/slave.cpp
@@ -429,7 +429,10 @@ void Slave::initialize()
       self().id + "/api/v1/resource_provider");
 
   Try<Owned<LocalResourceProviderDaemon>> _localResourceProviderDaemon =
-    LocalResourceProviderDaemon::create(localResourceProviderURL, flags);
+    LocalResourceProviderDaemon::create(
+        localResourceProviderURL,
+        flags,
+        secretGenerator);
 
   if (_localResourceProviderDaemon.isError()) {
     EXIT(EXIT_FAILURE)
@@ -1227,7 +1230,8 @@ void Slave::registered(
         CHECK_SOME(state::checkpoint(path, info_));
       }
 
-      // Start the local resource providers daemon once we have the slave id.
+      // We start the local resource providers daemon once the agent is
+      // running, so the resource providers can use the agent API.
       localResourceProviderDaemon->start(info.id());
 
       // Setup a timer so that the agent attempts to re-register if it
@@ -1333,6 +1337,10 @@ void Slave::reregistered(
       state = RUNNING;
       taskStatusUpdateManager->resume(); // Resume status updates.
 
+      // We start the local resource providers daemon once the agent is
+      // running, so the resource providers can use the agent API.
+      localResourceProviderDaemon->start(info.id());
+
       // Setup a timer so that the agent attempts to re-register if it
       // doesn't receive a ping from the master for an extended period
       // of time. This needs to be done once re-registered, in case we
@@ -6328,9 +6336,6 @@ Future<Nothing> Slave::recover(const Try<state::State>& state)
     } else {
       info = slaveState->info.get(); // Recover the slave info.
 
-      // Start the local resource providers daemon once we have the slave id.
-      localResourceProviderDaemon->start(info.id());
-
       // Recover the frameworks.
       foreachvalue (const FrameworkState& frameworkState,
                     slaveState->frameworks) {