Repository: mesos Updated Branches: refs/heads/master ad2a80ef6 -> b9998d147
Changed the ObjectApprover interface for optional subject and objects. Review 47505 changed the Request.object and subject to become optional fields.This patch adapts the ObjectApprover interface to deal with this behavior. Review: https://reviews.apache.org/r/48101/ Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/b9998d14 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/b9998d14 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/b9998d14 Branch: refs/heads/master Commit: b9998d1473d50fe8fe4001c69c44dbfba16d7fea Parents: ad2a80e Author: Joerg Schad <jo...@mesosphere.io> Authored: Tue May 31 20:57:18 2016 -0600 Committer: Vinod Kone <vinodk...@gmail.com> Committed: Tue May 31 20:57:18 2016 -0600 ---------------------------------------------------------------------- include/mesos/authorizer/authorizer.hpp | 5 +- src/authorizer/local/authorizer.cpp | 208 ++++++++++++++------------- src/authorizer/local/authorizer.hpp | 2 +- src/master/http.cpp | 2 +- src/tests/mesos.cpp | 2 +- src/tests/mesos.hpp | 2 +- 6 files changed, 114 insertions(+), 107 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/b9998d14/include/mesos/authorizer/authorizer.hpp ---------------------------------------------------------------------- diff --git a/include/mesos/authorizer/authorizer.hpp b/include/mesos/authorizer/authorizer.hpp index ea49681..452a92b 100644 --- a/include/mesos/authorizer/authorizer.hpp +++ b/include/mesos/authorizer/authorizer.hpp @@ -72,7 +72,8 @@ public: * NOTE: As this function can be used synchronously by actors * it is essential that it does not block! */ - virtual Try<bool> approved(const Object& object) const noexcept = 0; + virtual Try<bool> approved( + const Option<Object>& object) const noexcept = 0; virtual ~ObjectApprover() = default; }; @@ -153,7 +154,7 @@ public: * @return An `ObjectApprover` for the given `subject` and `action`. */ virtual process::Future<process::Owned<ObjectApprover>> getObjectApprover( - const authorization::Subject& subject, + const Option<authorization::Subject>& subject, const authorization::Action& action) = 0; protected: http://git-wip-us.apache.org/repos/asf/mesos/blob/b9998d14/src/authorizer/local/authorizer.cpp ---------------------------------------------------------------------- diff --git a/src/authorizer/local/authorizer.cpp b/src/authorizer/local/authorizer.cpp index 5f73f03..e88027d 100644 --- a/src/authorizer/local/authorizer.cpp +++ b/src/authorizer/local/authorizer.cpp @@ -168,7 +168,7 @@ class LocalAuthorizerObjectApprover : public ObjectApprover public: LocalAuthorizerObjectApprover( const vector<GenericACL>& acls, - const authorization::Subject& subject, + const Option<authorization::Subject>& subject, const authorization::Action& action, const bool permissive) : acls_(acls), @@ -177,11 +177,11 @@ public: permissive_(permissive) {} virtual Try<bool> approved( - const ObjectApprover::Object& object) const noexcept override { + const Option<ObjectApprover::Object>& object) const noexcept override { // Construct subject. ACL::Entity aclSubject; - if (subject_.has_value()) { - aclSubject.add_values(subject_.value()); + if (subject_.isSome()) { + aclSubject.add_values(subject_->value()); aclSubject.set_type(mesos::ACL::Entity::SOME); } else { aclSubject.set_type(mesos::ACL::Entity::ANY); @@ -189,112 +189,114 @@ public: // Construct object. ACL::Entity aclObject; - switch (action_) { - // All actions using `object.value` for authorization. - // Missing `object.value` implies 'ANY'. - case authorization::REGISTER_FRAMEWORK_WITH_ROLE: - case authorization::TEARDOWN_FRAMEWORK_WITH_PRINCIPAL: - case authorization::RUN_TASK_WITH_USER: - case authorization::RESERVE_RESOURCES_WITH_ROLE: - case authorization::UNRESERVE_RESOURCES_WITH_PRINCIPAL: - case authorization::CREATE_VOLUME_WITH_ROLE: - case authorization::DESTROY_VOLUME_WITH_PRINCIPAL: - case authorization::GET_QUOTA_WITH_ROLE: - case authorization::UPDATE_QUOTA_WITH_ROLE: - case authorization::SET_QUOTA_WITH_ROLE: - case authorization::DESTROY_QUOTA_WITH_PRINCIPAL: - case authorization::GET_WEIGHT_WITH_ROLE: - case authorization::UPDATE_WEIGHT_WITH_ROLE: - case authorization::GET_ENDPOINT_WITH_PATH: { - // Construct object. - if (object.value != NULL) { - aclObject.add_values(*(object.value)); + + if (object.isNone()) { + aclObject.set_type(mesos::ACL::Entity::ANY); + } else { + switch (action_) { + // All actions using `object.value` for authorization. + case authorization::REGISTER_FRAMEWORK_WITH_ROLE: + case authorization::TEARDOWN_FRAMEWORK_WITH_PRINCIPAL: + case authorization::RUN_TASK_WITH_USER: + case authorization::RESERVE_RESOURCES_WITH_ROLE: + case authorization::UNRESERVE_RESOURCES_WITH_PRINCIPAL: + case authorization::CREATE_VOLUME_WITH_ROLE: + case authorization::DESTROY_VOLUME_WITH_PRINCIPAL: + case authorization::GET_QUOTA_WITH_ROLE: + case authorization::UPDATE_QUOTA_WITH_ROLE: + case authorization::SET_QUOTA_WITH_ROLE: + case authorization::DESTROY_QUOTA_WITH_PRINCIPAL: + case authorization::GET_WEIGHT_WITH_ROLE: + case authorization::UPDATE_WEIGHT_WITH_ROLE: + case authorization::GET_ENDPOINT_WITH_PATH: { + // Check object has the required types set. + CHECK_NOTNULL(object->value); + + aclObject.add_values(*(object->value)); aclObject.set_type(mesos::ACL::Entity::SOME); - } else { - aclObject.set_type(mesos::ACL::Entity::ANY); - } - break; - } - case authorization::ACCESS_MESOS_LOG: { - aclObject.set_type(mesos::ACL::Entity::ANY); + break; + } + case authorization::ACCESS_MESOS_LOG: { + aclObject.set_type(mesos::ACL::Entity::ANY); - break; - } - case authorization::ACCESS_SANDBOX: { - // Check object has the required types set. - CHECK_NOTNULL(object.executor_info); - CHECK_NOTNULL(object.framework_info); + break; + } + case authorization::ACCESS_SANDBOX: { + // Check object has the required types set. + CHECK_NOTNULL(object->executor_info); + CHECK_NOTNULL(object->framework_info); + + if (object->executor_info->command().has_user()) { + aclObject.add_values(object->executor_info->command().user()); + aclObject.set_type(mesos::ACL::Entity::SOME); + } else { + aclObject.add_values(object->framework_info->user()); + aclObject.set_type(mesos::ACL::Entity::SOME); + } - if (object.executor_info->command().has_user()) { - aclObject.add_values(object.executor_info->command().user()); - aclObject.set_type(mesos::ACL::Entity::SOME); - } else { - aclObject.add_values(object.framework_info->user()); - aclObject.set_type(mesos::ACL::Entity::SOME); + break; } + case authorization::VIEW_FRAMEWORK: { + // Check object has the required types set. + CHECK_NOTNULL(object->framework_info); - break; - } - case authorization::VIEW_FRAMEWORK: { - // Check object has the required types set. - CHECK_NOTNULL(object.framework_info); + aclObject.add_values(object->framework_info->user()); + aclObject.set_type(mesos::ACL::Entity::SOME); - aclObject.add_values(object.framework_info->user()); - aclObject.set_type(mesos::ACL::Entity::SOME); + break; + } + case authorization::VIEW_TASK: { + CHECK(object->task != NULL || object->task_info != NULL); + CHECK_NOTNULL(object->framework_info); + + // First we consider either whether `Task` or `TaskInfo` + // have `user` set. As fallback we use `FrameworkInfo.user`. + Option<string> taskUser = None(); + if (object->task != NULL && object->task->has_user()) { + taskUser = object->task->user(); + } else if (object->task_info != NULL) { + // Within TaskInfo the user can be either set in `command` + // or `executor.command`. + if (object->task_info->has_command() && + object->task_info->command().has_user()) { + taskUser = object->task_info->command().user(); + } else if (object->task_info->has_executor() && + object->task_info->executor().command().has_user()) { + taskUser = object->task_info->executor().command().user(); + } + } - break; - } - case authorization::VIEW_TASK: { - CHECK(object.task != NULL || object.task_info != NULL); - CHECK_NOTNULL(object.framework_info); - - // First we consider either whether `Task` or `TaskInfo` - // have `user` set. As fallback we use `FrameworkInfo.user`. - Option<string> taskUser = None(); - if (object.task != NULL && object.task->has_user()) { - taskUser = object.task->user(); - } else if (object.task_info != NULL) { - // Within TaskInfo the user can be either set in `command` - // or `executor.command`. - if (object.task_info->has_command() && - object.task_info->command().has_user()) { - taskUser = object.task_info->command().user(); - } else if (object.task_info->has_executor() && - object.task_info->executor().command().has_user()) { - taskUser = object.task_info->executor().command().user(); + // In case there is no `user` set on task level we fallback + // to the `FrameworkInfo.user`. + if (taskUser.isNone()) { + taskUser = object->framework_info->user(); } - } + aclObject.add_values(taskUser.get()); + aclObject.set_type(mesos::ACL::Entity::SOME); - // In case there is no `user` set on task level we fallback - // to the `FrameworkInfo.user`. - if (taskUser.isNone()) { - taskUser = object.framework_info->user(); + break; } - aclObject.add_values(taskUser.get()); - aclObject.set_type(mesos::ACL::Entity::SOME); - - break; - } - case authorization::VIEW_EXECUTOR: { - CHECK_NOTNULL(object.executor_info); - CHECK_NOTNULL(object.framework_info); + case authorization::VIEW_EXECUTOR: { + CHECK_NOTNULL(object->executor_info); + CHECK_NOTNULL(object->framework_info); + + if (object->executor_info->command().has_user()) { + aclObject.add_values(object->executor_info->command().user()); + aclObject.set_type(mesos::ACL::Entity::SOME); + } else { + aclObject.add_values(object->framework_info->user()); + aclObject.set_type(mesos::ACL::Entity::SOME); + } - if (object.executor_info->command().has_user()) { - aclObject.add_values(object.executor_info->command().user()); - aclObject.set_type(mesos::ACL::Entity::SOME); - } else { - aclObject.add_values(object.framework_info->user()); - aclObject.set_type(mesos::ACL::Entity::SOME); + break; } - - break; + case authorization::UNKNOWN: + LOG(WARNING) << "Authorization for action '" << action_ + << "' is not defined and therefore not authorized"; + return false; + break; } - case authorization::UNKNOWN: - LOG(WARNING) << "Authorization for action '" << action_ - << "' is not defined and therefore not authorized"; - return false; - break; } return approved(acls_, aclSubject, aclObject); @@ -317,7 +319,7 @@ private: } const vector<GenericACL> acls_; - const authorization::Subject subject_; + const Option<authorization::Subject> subject_; const authorization::Action action_; const bool permissive_; }; @@ -368,7 +370,11 @@ public: { return getObjectApprover(request.subject(), request.action()) .then([=](const Owned<ObjectApprover>& objectApprover) -> Future<bool> { - ObjectApprover::Object object(request.object()); + Option<ObjectApprover::Object> object = None(); + if (request.has_object()) { + object = ObjectApprover::Object(request.object()); + } + Try<bool> result = objectApprover->approved(object); if (result.isError()) { return Failure(result.error()); @@ -378,7 +384,7 @@ public: } Future<Owned<ObjectApprover>> getObjectApprover( - const authorization::Subject& subject, + const Option<authorization::Subject>& subject, const authorization::Action& action) { // Implementation of the ObjectApprover interface denying all objects. @@ -386,7 +392,7 @@ public: { public: virtual Try<bool> approved( - const ObjectApprover::Object& object) const noexcept override + const Option<ObjectApprover::Object>& object) const noexcept override { return false; } @@ -794,7 +800,7 @@ process::Future<bool> LocalAuthorizer::authorized( Future<Owned<ObjectApprover>> LocalAuthorizer::getObjectApprover( - const authorization::Subject& subject, + const Option<authorization::Subject>& subject, const authorization::Action& action) { return dispatch( http://git-wip-us.apache.org/repos/asf/mesos/blob/b9998d14/src/authorizer/local/authorizer.hpp ---------------------------------------------------------------------- diff --git a/src/authorizer/local/authorizer.hpp b/src/authorizer/local/authorizer.hpp index 9242889..794443a 100644 --- a/src/authorizer/local/authorizer.hpp +++ b/src/authorizer/local/authorizer.hpp @@ -66,7 +66,7 @@ public: const authorization::Request& request); virtual process::Future<process::Owned<ObjectApprover>> getObjectApprover( - const authorization::Subject& subject, + const Option<authorization::Subject>& subject, const authorization::Action& action); private: http://git-wip-us.apache.org/repos/asf/mesos/blob/b9998d14/src/master/http.cpp ---------------------------------------------------------------------- diff --git a/src/master/http.cpp b/src/master/http.cpp index 1245326..824c6e5 100644 --- a/src/master/http.cpp +++ b/src/master/http.cpp @@ -170,7 +170,7 @@ class AcceptingObjectApprover : public ObjectApprover { public: virtual Try<bool> approved( - const ObjectApprover::Object& object) const noexcept override + const Option<ObjectApprover::Object>& object) const noexcept override { return true; } http://git-wip-us.apache.org/repos/asf/mesos/blob/b9998d14/src/tests/mesos.cpp ---------------------------------------------------------------------- diff --git a/src/tests/mesos.cpp b/src/tests/mesos.cpp index 6c64bd5..51d223a 100644 --- a/src/tests/mesos.cpp +++ b/src/tests/mesos.cpp @@ -675,7 +675,7 @@ MockAuthorizer::MockAuthorizer() { public: virtual Try<bool> approved( - const ObjectApprover::Object& object) const noexcept override + const Option<ObjectApprover::Object>& object) const noexcept override { return true; } http://git-wip-us.apache.org/repos/asf/mesos/blob/b9998d14/src/tests/mesos.hpp ---------------------------------------------------------------------- diff --git a/src/tests/mesos.hpp b/src/tests/mesos.hpp index 5d7b5d1..259c24d 100644 --- a/src/tests/mesos.hpp +++ b/src/tests/mesos.hpp @@ -1716,7 +1716,7 @@ public: MOCK_METHOD2( getObjectApprover, process::Future<process::Owned<ObjectApprover>>( - const authorization::Subject& subject, + const Option<authorization::Subject>& subject, const authorization::Action& action)); };