You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ti...@apache.org on 2016/01/06 18:32:06 UTC

[3/5] mesos git commit: Quota: Implemented quota remove authorization.

Quota: Implemented quota remove authorization.

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


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

Branch: refs/heads/master
Commit: 4fe7880a44646f6659f6c0e9a013735cb6071e5d
Parents: 6998047
Author: Jan Schlicht <ja...@mesosphere.io>
Authored: Wed Jan 6 18:20:11 2016 +0100
Committer: Till Toenshoff <to...@me.com>
Committed: Wed Jan 6 18:20:11 2016 +0100

----------------------------------------------------------------------
 include/mesos/quota/quota.proto |  3 ++
 src/master/master.hpp           |  9 ++++-
 src/master/quota_handler.cpp    | 74 +++++++++++++++++++++++++++++++-----
 3 files changed, 75 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/4fe7880a/include/mesos/quota/quota.proto
----------------------------------------------------------------------
diff --git a/include/mesos/quota/quota.proto b/include/mesos/quota/quota.proto
index ab505b1..338412e 100644
--- a/include/mesos/quota/quota.proto
+++ b/include/mesos/quota/quota.proto
@@ -38,6 +38,9 @@ message QuotaInfo {
   // dynamic reservations.
   optional string role = 1;
 
+  // Principal which set the quota. Currently only operators can set quotas.
+  optional string principal = 2;
+
   // Resources which are guaranteed to be allocatable by role.
   // NOTE: `guarantee.role` should not specify any role except '*',
   // because quota does not reserve specific resources.

http://git-wip-us.apache.org/repos/asf/mesos/blob/4fe7880a/src/master/master.hpp
----------------------------------------------------------------------
diff --git a/src/master/master.hpp b/src/master/master.hpp
index 2936d32..f764915 100644
--- a/src/master/master.hpp
+++ b/src/master/master.hpp
@@ -997,14 +997,21 @@ private:
     // (including rescinding) is moved to allocator.
     void rescindOffers(const mesos::quota::QuotaInfo& request) const;
 
-    process::Future<bool> authorize(
+    process::Future<bool> authorizeSetQuota(
         const Option<std::string>& principal,
         const std::string& role) const;
 
+    process::Future<bool> authorizeRemoveQuota(
+        const Option<std::string>& requestPrincipal,
+        const Option<std::string>& quotaPrincipal) const;
+
     process::Future<process::http::Response> _set(
         const mesos::quota::QuotaInfo& quota,
         bool forced) const;
 
+    process::Future<process::http::Response> _remove(
+        const std::string& role) const;
+
     // To perform actions related to quota management, we require access to the
     // master data structures. No synchronization primitives are needed here
     // since `QuotaHandler`'s functions are invoked in the Master's actor.

http://git-wip-us.apache.org/repos/asf/mesos/blob/4fe7880a/src/master/quota_handler.cpp
----------------------------------------------------------------------
diff --git a/src/master/quota_handler.cpp b/src/master/quota_handler.cpp
index ac4da74..93960f3 100644
--- a/src/master/quota_handler.cpp
+++ b/src/master/quota_handler.cpp
@@ -299,7 +299,7 @@ Future<http::Response> Master::QuotaHandler::set(
         request.body + "': " + create.error());
   }
 
-  const QuotaInfo& quotaInfo = create.get();
+  QuotaInfo quotaInfo = create.get();
 
   // Check that the `QuotaInfo` is a valid quota request.
   Try<Nothing> validate = quota::validation::quotaInfo(quotaInfo);
@@ -335,13 +335,16 @@ Future<http::Response> Master::QuotaHandler::set(
         request.body + "': " + force.error());
   }
 
-  const bool forced = force.isSome() ? force.get().value : false;
-
   // Extract principal from request credentials.
-  Option<string> principal =
-    credential.isSome() ? credential.get().principal() : Option<string>::none();
+  Option<string> principal = None();
+  if (credential.isSome()) {
+    principal = credential.get().principal();
+    quotaInfo.set_principal(principal.get());
+  }
 
-  return authorize(principal, quotaInfo.role())
+  const bool forced = force.isSome() ? force.get().value : false;
+
+  return authorizeSetQuota(principal, quotaInfo.role())
     .then(defer(master->self(), [=](bool authorized) -> Future<http::Response> {
       if (!authorized) {
         return Unauthorized("Mesos master");
@@ -406,14 +409,12 @@ Future<http::Response> Master::QuotaHandler::remove(
 {
   VLOG(1) << "Removing quota for request path: '" << request.url.path << "'";
 
-    // Authenticate the request.
+  // Authenticate the request.
   Result<Credential> credential = master->http.authenticate(request);
   if (credential.isError()) {
     return Unauthorized("Mesos master", credential.error());
   }
 
-  // TODO(nfnt): Authorize the request.
-
   // Check that the request type is DELETE which is guaranteed by the master.
   CHECK_EQ("DELETE", request.method);
 
@@ -451,6 +452,27 @@ Future<http::Response> Master::QuotaHandler::remove(
         "': Role '" + role + "' has no quota set");
   }
 
+  // Extract principal from request credentials.
+  Option<string> principal =
+    credential.isSome() ? credential.get().principal() : Option<string>::none();
+
+  Option<string> quota_principal = master->quotas[role].info.has_principal()
+    ? master->quotas[role].info.principal()
+    : Option<string>::none();
+
+  return authorizeRemoveQuota(principal, quota_principal)
+    .then(defer(master->self(), [=](bool authorized) -> Future<http::Response> {
+      if (!authorized) {
+        return Unauthorized("Mesos master");
+      }
+
+      return _remove(role);
+    }));
+}
+
+
+Future<http::Response> Master::QuotaHandler::_remove(const string& role) const
+{
   // Remove quota from the quota-related local state. We do this before
   // updating the registry in order to make sure that we are not already
   // trying to remove quota for this role (since this is a multi-phase event).
@@ -493,7 +515,7 @@ Future<http::Response> Master::QuotaHandler::status(
 }
 
 
-Future<bool> Master::QuotaHandler::authorize(
+Future<bool> Master::QuotaHandler::authorizeSetQuota(
     const Option<string>& principal,
     const string& role) const
 {
@@ -518,6 +540,38 @@ Future<bool> Master::QuotaHandler::authorize(
   return master->authorizer.get()->authorize(request);
 }
 
+
+Future<bool> Master::QuotaHandler::authorizeRemoveQuota(
+    const Option<string>& requestPrincipal,
+    const Option<string>& quotaPrincipal) const
+{
+  if (master->authorizer.isNone()) {
+    return true;
+  }
+
+  LOG(INFO) << "Authorizing principal '"
+            << (requestPrincipal.isSome() ? requestPrincipal.get() : "ANY")
+            << "' to remove quota set by '"
+            << (quotaPrincipal.isSome() ? quotaPrincipal.get() : "ANY")
+            << "'";
+
+  mesos::ACL::RemoveQuota request;
+
+  if (requestPrincipal.isSome()) {
+    request.mutable_principals()->add_values(requestPrincipal.get());
+  } else {
+    request.mutable_principals()->set_type(mesos::ACL::Entity::ANY);
+  }
+
+  if (quotaPrincipal.isSome()) {
+    request.mutable_quota_principals()->add_values(quotaPrincipal.get());
+  } else {
+    request.mutable_quota_principals()->set_type(mesos::ACL::Entity::ANY);
+  }
+
+  return master->authorizer.get()->authorize(request);
+}
+
 } // namespace master {
 } // namespace internal {
 } // namespace mesos {