You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by an...@apache.org on 2017/09/29 20:31:43 UTC

[10/11] mesos git commit: Added authorization for 'MARK_AGENT_GONE' call.

Added authorization for 'MARK_AGENT_GONE' call.

This change adds the relevant ACL's for doing AuthZ (any or none
access).

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


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

Branch: refs/heads/master
Commit: 11dbb52a6b9339e1ad243f00c92601e108499997
Parents: 6001e8a
Author: Anand Mazumdar <an...@apache.org>
Authored: Fri Sep 29 11:58:41 2017 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Fri Sep 29 13:31:08 2017 -0700

----------------------------------------------------------------------
 include/mesos/authorizer/acls.proto       | 11 +++++
 include/mesos/authorizer/authorizer.proto |  4 ++
 src/authorizer/local/authorizer.cpp       | 15 +++++++
 src/master/http.cpp                       | 29 +++++++++++++
 src/master/master.hpp                     |  3 ++
 src/tests/api_tests.cpp                   | 57 ++++++++++++++++++++++++++
 6 files changed, 119 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/11dbb52a/include/mesos/authorizer/acls.proto
----------------------------------------------------------------------
diff --git a/include/mesos/authorizer/acls.proto b/include/mesos/authorizer/acls.proto
index 9109283..587b714 100644
--- a/include/mesos/authorizer/acls.proto
+++ b/include/mesos/authorizer/acls.proto
@@ -404,6 +404,16 @@ message ACL {
     // access.
     required Entity machines = 2;
   }
+
+  // Which principals are authorized to mark an agent as gone.
+  message MarkAgentGone {
+    // Subjects: HTTP Username.
+    required Entity principals = 1;
+
+    // Objects: Given implicitly. Use Entity type ANY or NONE to allow or deny
+    // access.
+    required Entity agents = 2;
+  }
 }
 
 
@@ -474,4 +484,5 @@ message ACLs {
   repeated ACL.StartMaintenance start_maintenances = 37;
   repeated ACL.StopMaintenance stop_maintenances = 38;
   repeated ACL.GetMaintenanceStatus get_maintenance_statuses = 39;
+  repeated ACL.MarkAgentGone mark_agents_gone = 40;
 }

http://git-wip-us.apache.org/repos/asf/mesos/blob/11dbb52a/include/mesos/authorizer/authorizer.proto
----------------------------------------------------------------------
diff --git a/include/mesos/authorizer/authorizer.proto b/include/mesos/authorizer/authorizer.proto
index 38f0e0b..87a8057 100644
--- a/include/mesos/authorizer/authorizer.proto
+++ b/include/mesos/authorizer/authorizer.proto
@@ -213,6 +213,10 @@ enum Action {
 
   // This action will set objects of type `MachineID`.
   GET_MAINTENANCE_STATUS = 33;
+
+  // This action will not fill in any object fields, since a principal is
+  // either allowed to mark an agent as gone or is unauthorized.
+  MARK_AGENT_GONE = 34;
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/11dbb52a/src/authorizer/local/authorizer.cpp
----------------------------------------------------------------------
diff --git a/src/authorizer/local/authorizer.cpp b/src/authorizer/local/authorizer.cpp
index 82ae846..2fe7b87 100644
--- a/src/authorizer/local/authorizer.cpp
+++ b/src/authorizer/local/authorizer.cpp
@@ -398,6 +398,7 @@ public:
           break;
         case authorization::GET_MAINTENANCE_SCHEDULE:
         case authorization::GET_MAINTENANCE_STATUS:
+        case authorization::MARK_AGENT_GONE:
         case authorization::REGISTER_AGENT:
         case authorization::SET_LOG_LEVEL:
         case authorization::START_MAINTENANCE:
@@ -666,6 +667,7 @@ public:
         case authorization::KILL_NESTED_CONTAINER:
         case authorization::LAUNCH_NESTED_CONTAINER:
         case authorization::LAUNCH_NESTED_CONTAINER_SESSION:
+        case authorization::MARK_AGENT_GONE:
         case authorization::REGISTER_AGENT:
         case authorization::REMOVE_NESTED_CONTAINER:
         case authorization::RUN_TASK:
@@ -876,6 +878,7 @@ public:
       case authorization::KILL_NESTED_CONTAINER:
       case authorization::LAUNCH_NESTED_CONTAINER:
       case authorization::LAUNCH_NESTED_CONTAINER_SESSION:
+      case authorization::MARK_AGENT_GONE:
       case authorization::REGISTER_AGENT:
       case authorization::REMOVE_NESTED_CONTAINER:
       case authorization::RUN_TASK:
@@ -1040,6 +1043,7 @@ public:
       case authorization::GET_MAINTENANCE_SCHEDULE:
       case authorization::GET_MAINTENANCE_STATUS:
       case authorization::KILL_NESTED_CONTAINER:
+      case authorization::MARK_AGENT_GONE:
       case authorization::REGISTER_AGENT:
       case authorization::REMOVE_NESTED_CONTAINER:
       case authorization::RUN_TASK:
@@ -1333,6 +1337,17 @@ private:
         }
 
         return acls_;
+      case authorization::MARK_AGENT_GONE:
+        foreach (const ACL::MarkAgentGone& acl,
+                 acls.mark_agents_gone()) {
+          GenericACL acl_;
+          acl_.subjects = acl.principals();
+          acl_.objects = acl.agents();
+
+          acls_.push_back(acl_);
+        }
+
+        return acls_;
       case authorization::REGISTER_FRAMEWORK:
       case authorization::CREATE_VOLUME:
       case authorization::RESERVE_RESOURCES:

http://git-wip-us.apache.org/repos/asf/mesos/blob/11dbb52a/src/master/http.cpp
----------------------------------------------------------------------
diff --git a/src/master/http.cpp b/src/master/http.cpp
index 66a391f..42139be 100644
--- a/src/master/http.cpp
+++ b/src/master/http.cpp
@@ -5297,8 +5297,37 @@ Future<Response> Master::Http::markAgentGone(
 {
   CHECK_EQ(mesos::master::Call::MARK_AGENT_GONE, call.type());
 
+  Future<Owned<ObjectApprover>> approver;
+
+  if (master->authorizer.isSome()) {
+    Option<authorization::Subject> subject = createSubject(principal);
+
+    approver = master->authorizer.get()->getObjectApprover(
+        subject, authorization::MARK_AGENT_GONE);
+  } else {
+    approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
+  }
+
   const SlaveID& slaveId = call.mark_agent_gone().slave_id();
 
+  return approver.then(defer(master->self(),
+      [this, slaveId](const Owned<ObjectApprover>& approver)
+          -> Future<Response> {
+    Try<bool> approved = approver->approved((ObjectApprover::Object()));
+
+    if (approved.isError()) {
+      return InternalServerError("Authorization error: " + approved.error());
+    } else if (!approved.get()) {
+      return Forbidden();
+    }
+
+    return _markAgentGone(slaveId);
+  }));
+}
+
+
+Future<Response> Master::Http::_markAgentGone(const SlaveID& slaveId) const
+{
   LOG(INFO) << "Marking agent '" << slaveId << "' as gone";
 
   if (master->slaves.gone.contains(slaveId)) {

http://git-wip-us.apache.org/repos/asf/mesos/blob/11dbb52a/src/master/master.hpp
----------------------------------------------------------------------
diff --git a/src/master/master.hpp b/src/master/master.hpp
index a17378e..23b864d 100644
--- a/src/master/master.hpp
+++ b/src/master/master.hpp
@@ -1672,6 +1672,9 @@ private:
         const Option<process::http::authentication::Principal>& principal,
         ContentType contentType) const;
 
+    process::Future<process::http::Response> _markAgentGone(
+        const SlaveID& slaveId) const;
+
     Master* master;
 
     // NOTE: The quota specific pieces of the Operator API are factored

http://git-wip-us.apache.org/repos/asf/mesos/blob/11dbb52a/src/tests/api_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/api_tests.cpp b/src/tests/api_tests.cpp
index 9e2945c..3d0db3b 100644
--- a/src/tests/api_tests.cpp
+++ b/src/tests/api_tests.cpp
@@ -3583,6 +3583,63 @@ TEST_P_TEMP_DISABLED_ON_WINDOWS(MasterAPITest, MarkRegisteredAgentGone)
 }
 
 
+// This test verifies that unauthorized principals are unable to
+// mark agents as gone.
+TEST_P_TEMP_DISABLED_ON_WINDOWS(MasterAPITest,
+                                MarkRegisteredAgentGoneUnauthorized)
+{
+  master::Flags masterFlags = CreateMasterFlags();
+
+  {
+    // Default principal is not allowed to mark agents as gone.
+    mesos::ACL::MarkAgentGone* acl =
+      masterFlags.acls.get().add_mark_agents_gone();
+
+    acl->mutable_principals()->add_values(DEFAULT_CREDENTIAL.principal());
+    acl->mutable_agents()->set_type(mesos::ACL::Entity::NONE);
+  }
+
+  Try<Owned<cluster::Master>> master = this->StartMaster(masterFlags);
+  ASSERT_SOME(master);
+
+  Owned<MasterDetector> detector = master.get()->createDetector();
+
+  Future<SlaveRegisteredMessage> slaveRegisteredMessage =
+    FUTURE_PROTOBUF(SlaveRegisteredMessage(), master.get()->pid, _);
+
+  slave::Flags slaveFlags = CreateSlaveFlags();
+
+  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), slaveFlags);
+  ASSERT_SOME(slave);
+
+  // Ensure that the agent is registered successfully with the master
+  // before marking it as gone.
+  AWAIT_READY(slaveRegisteredMessage);
+
+  // Mark the agent as gone. This should fail due to an authorization error.
+
+  ContentType contentType = GetParam();
+
+  v1::master::Call v1Call;
+  v1Call.set_type(v1::master::Call::MARK_AGENT_GONE);
+
+  v1::master::Call::MarkAgentGone* markAgentGone =
+    v1Call.mutable_mark_agent_gone();
+
+  markAgentGone->mutable_agent_id()->CopyFrom(
+      evolve(slaveRegisteredMessage->slave_id()));
+
+  Future<http::Response> response = http::post(
+      master.get()->pid,
+      "api/v1",
+      createBasicAuthHeaders(DEFAULT_CREDENTIAL),
+      serialize(contentType, v1Call),
+      stringify(contentType));
+
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(http::Forbidden().status, response);
+}
+
+
 // This test verifies that the master correctly sends 'TASK_GONE_BY_OPERATOR'
 // status updates when an agent running the tasks is marked as gone.
 //