Repository: mesos
Updated Branches:
  refs/heads/master f22af9805 -> 8443b1848


Enabled authorization for Mesos log access.

Uses the authorization primitives in `mesos::internal::Files` to add
protection of the Mesos logs on both master and agents.

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


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

Branch: refs/heads/master
Commit: 8443b18489c48996df0a88f90baf260a0fb12176
Parents: f22af98
Author: Alexander Rojas <[email protected]>
Authored: Sun May 29 11:16:03 2016 -0700
Committer: Adam B <[email protected]>
Committed: Mon May 30 00:59:14 2016 -0700

----------------------------------------------------------------------
 include/mesos/authorizer/acls.proto       | 11 +++++++++++
 include/mesos/authorizer/authorizer.proto |  4 ++++
 src/authorizer/local/authorizer.cpp       | 19 ++++++++++++++++++-
 src/master/master.cpp                     | 25 +++++++++++++++++++++++--
 src/master/master.hpp                     |  3 +++
 src/slave/slave.cpp                       | 25 +++++++++++++++++++++++--
 src/slave/slave.hpp                       |  3 +++
 7 files changed, 85 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/8443b184/include/mesos/authorizer/acls.proto
----------------------------------------------------------------------
diff --git a/include/mesos/authorizer/acls.proto 
b/include/mesos/authorizer/acls.proto
index b05586a..db55ee5 100644
--- a/include/mesos/authorizer/acls.proto
+++ b/include/mesos/authorizer/acls.proto
@@ -223,6 +223,16 @@ message ACL {
     // executors/tasks sandboxes can be accessed.
     optional Entity users = 2;
   }
+
+  // Which principals are authorized to access the Mesos logs.
+  message AccessMesosLog {
+    // Subjects: HTTP Username.
+    required Entity principals = 1;
+
+    // Objects: Given implicitly. Use Entity type ANY or NONE to allow or deny
+    // access.
+    optional Entity logs = 2;
+  }
 }
 
 
@@ -271,4 +281,5 @@ message ACLs {
   repeated ACL.ViewTask view_tasks = 17;
   repeated ACL.ViewExecutor view_executors = 18;
   repeated ACL.AccessSandbox access_sandboxes = 19;
+  repeated ACL.AccessMesosLog access_mesos_logs = 20;
 }

http://git-wip-us.apache.org/repos/asf/mesos/blob/8443b184/include/mesos/authorizer/authorizer.proto
----------------------------------------------------------------------
diff --git a/include/mesos/authorizer/authorizer.proto 
b/include/mesos/authorizer/authorizer.proto
index 3ff6785..4478bbd 100644
--- a/include/mesos/authorizer/authorizer.proto
+++ b/include/mesos/authorizer/authorizer.proto
@@ -85,6 +85,10 @@ enum Action {
   // This action will have a `FrameworkInfo` and `ExecutorInfo` set,
   // allowing both as objects in order to perform authorization.
   ACCESS_SANDBOX = 17;
+
+  // This action will not fill in any object fields, since the object
+  // is the master/agent log itself.
+  ACCESS_MESOS_LOG = 18;
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/8443b184/src/authorizer/local/authorizer.cpp
----------------------------------------------------------------------
diff --git a/src/authorizer/local/authorizer.cpp 
b/src/authorizer/local/authorizer.cpp
index 7ddb323..547bbdd 100644
--- a/src/authorizer/local/authorizer.cpp
+++ b/src/authorizer/local/authorizer.cpp
@@ -273,6 +273,17 @@ public:
 
         return authorized(request, acls_);
         break;
+      case authorization::ACCESS_MESOS_LOG:
+        foreach (const ACL::AccessMesosLog& acl, acls.access_mesos_logs()) {
+          GenericACL acl_;
+          acl_.subjects = acl.principals();
+          acl_.objects = acl.logs();
+
+          acls_.push_back(acl_);
+        }
+
+        return authorized(request, acls_);
+        break;
       case authorization::ACCESS_SANDBOX: {
         authorization::Request realRequest;
         realRequest.set_action(authorization::ACCESS_SANDBOX);
@@ -303,7 +314,6 @@ public:
         return authorized(realRequest, acls_);
         break;
       }
-
       // TODO(joerg84): Add logic for the `VIEW_*` actions.
       case authorization::VIEW_FRAMEWORK:
       case authorization::VIEW_TASK:
@@ -504,6 +514,13 @@ Option<Error> LocalAuthorizer::validate(const ACLs& acls)
                  "together with deprecated set_quotas/remove_quotas!");
   }
 
+
+  foreach (const ACL::AccessMesosLog& acl, acls.access_mesos_logs()) {
+    if (acl.logs().type() == ACL::Entity::SOME) {
+      return Error("acls.access_mesos_logs type must be either NONE or ANY");
+    }
+  }
+
   return None();
 }
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/8443b184/src/master/master.cpp
----------------------------------------------------------------------
diff --git a/src/master/master.cpp b/src/master/master.cpp
index 67d3309..a6f740f 100644
--- a/src/master/master.cpp
+++ b/src/master/master.cpp
@@ -1156,10 +1156,14 @@ void Master::initialize()
   provide("", path::join(flags.webui_dir, "master/static/index.html"));
   provide("static", path::join(flags.webui_dir, "master/static"));
 
+  auto authorize = [this](const Option<string>& principal) {
+    return authorizeLogAccess(principal);
+  };
+
   // Expose the log file for the webui. Fall back to 'log_dir' if
   // an explicit file was not specified.
   if (flags.external_log_file.isSome()) {
-    files->attach(flags.external_log_file.get(), "/master/log")
+    files->attach(flags.external_log_file.get(), "/master/log", authorize)
       .onAny(defer(self(),
                    &Self::fileAttached,
                    lambda::_1,
@@ -1171,7 +1175,7 @@ void Master::initialize()
     if (log.isError()) {
       LOG(ERROR) << "Master log file cannot be found: " << log.error();
     } else {
-      files->attach(log.get(), "/master/log")
+      files->attach(log.get(), "/master/log", authorize)
         .onAny(defer(self(), &Self::fileAttached, lambda::_1, log.get()));
     }
   }
@@ -1406,6 +1410,23 @@ void Master::_exited(Framework* framework)
 }
 
 
+Future<bool> Master::authorizeLogAccess(const Option<std::string>& principal)
+{
+  if (authorizer.isNone()) {
+    return true;
+  }
+
+  authorization::Request request;
+  request.set_action(authorization::ACCESS_MESOS_LOG);
+
+  if (principal.isSome()) {
+    request.mutable_subject()->set_value(principal.get());
+  }
+
+  return authorizer.get()->authorized(request);
+}
+
+
 void Master::visit(const MessageEvent& event)
 {
   // There are three cases about the message's UPID with respect to

http://git-wip-us.apache.org/repos/asf/mesos/blob/8443b184/src/master/master.hpp
----------------------------------------------------------------------
diff --git a/src/master/master.hpp b/src/master/master.hpp
index 9cc79ef..eeeccdf 100644
--- a/src/master/master.hpp
+++ b/src/master/master.hpp
@@ -917,6 +917,9 @@ private:
     return leader.isSome() && leader.get() == info_;
   }
 
+  process::Future<bool> authorizeLogAccess(
+      const Option<std::string>& principal);
+
   /**
    * Returns whether the given role is on the whitelist.
    *

http://git-wip-us.apache.org/repos/asf/mesos/blob/8443b184/src/slave/slave.cpp
----------------------------------------------------------------------
diff --git a/src/slave/slave.cpp b/src/slave/slave.cpp
index 1ef8cfb..c235c14 100644
--- a/src/slave/slave.cpp
+++ b/src/slave/slave.cpp
@@ -776,10 +776,14 @@ void Slave::initialize()
           return http.containers(request, principal);
         });
 
+  auto authorize = [this](const Option<string>& principal) {
+    return authorizeLogAccess(principal);
+  };
+
   // Expose the log file for the webui. Fall back to 'log_dir' if
   // an explicit file was not specified.
   if (flags.external_log_file.isSome()) {
-    files->attach(flags.external_log_file.get(), "/slave/log")
+    files->attach(flags.external_log_file.get(), "/slave/log", authorize)
       .onAny(defer(self(),
                    &Self::fileAttached,
                    lambda::_1,
@@ -791,7 +795,7 @@ void Slave::initialize()
     if (log.isError()) {
       LOG(ERROR) << "Agent log file cannot be found: " << log.error();
     } else {
-      files->attach(log.get(), "/slave/log")
+      files->attach(log.get(), "/slave/log", authorize)
         .onAny(defer(self(), &Self::fileAttached, lambda::_1, log.get()));
     }
   }
@@ -5386,6 +5390,23 @@ double Slave::_executor_directory_max_allowed_age_secs()
 }
 
 
+Future<bool> Slave::authorizeLogAccess(const Option<std::string>& principal)
+{
+  if (authorizer.isNone()) {
+    return true;
+  }
+
+  authorization::Request request;
+  request.set_action(authorization::ACCESS_MESOS_LOG);
+
+  if (principal.isSome()) {
+    request.mutable_subject()->set_value(principal.get());
+  }
+
+  return authorizer.get()->authorized(request);
+}
+
+
 Future<bool> Slave::authorizeSandboxAccess(
     const Option<std::string>& principal,
     const FrameworkID& frameworkId,

http://git-wip-us.apache.org/repos/asf/mesos/blob/8443b184/src/slave/slave.hpp
----------------------------------------------------------------------
diff --git a/src/slave/slave.hpp b/src/slave/slave.hpp
index 26e94c6..52aeb0d 100644
--- a/src/slave/slave.hpp
+++ b/src/slave/slave.hpp
@@ -419,6 +419,9 @@ private:
   // exited.
   void _shutdownExecutor(Framework* framework, Executor* executor);
 
+  process::Future<bool> authorizeLogAccess(
+      const Option<std::string>& principal);
+
   Future<bool> authorizeSandboxAccess(
       const Option<std::string>& principal,
       const FrameworkID& frameworkId,

Reply via email to