You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ar...@apache.org on 2018/03/14 17:10:18 UTC
[8/8] mesos git commit: Added the ObjectApprovers to which unifies
authorization logic.
Added the ObjectApprovers to which unifies authorization logic.
Introduces the class `ObjectApprovers` which unifies the different
mechanisms used in Mesos in order to perform authorization.
This new class will supersede the `Acceptor` interfaces and their
logic.
Follow up patches will make use of this interface and remove
deprecated code.
Review: https://reviews.apache.org/r/65311
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/dc9eaeb2
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/dc9eaeb2
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/dc9eaeb2
Branch: refs/heads/master
Commit: dc9eaeb2667d154cba4cc0fa59825101b7987dc4
Parents: 28a20ba
Author: Alexander Rojas <al...@mesosphere.io>
Authored: Mon Jan 22 15:22:04 2018 +0100
Committer: Alexander Rojas <al...@mesosphere.io>
Committed: Wed Mar 14 18:09:20 2018 +0100
----------------------------------------------------------------------
src/common/http.cpp | 36 +++++++++++++++++
src/common/http.hpp | 103 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 139 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/dc9eaeb2/src/common/http.cpp
----------------------------------------------------------------------
diff --git a/src/common/http.cpp b/src/common/http.cpp
index 8d3a4ad..99d84cd 100644
--- a/src/common/http.cpp
+++ b/src/common/http.cpp
@@ -32,6 +32,7 @@
#include <mesos/quota/quota.hpp>
#include <process/authenticator.hpp>
+#include <process/collect.hpp>
#include <process/dispatch.hpp>
#include <process/future.hpp>
#include <process/http.hpp>
@@ -861,6 +862,41 @@ const AuthorizationCallbacks createAuthorizationCallbacks(
return callbacks;
}
+Future<Owned<ObjectApprovers>> ObjectApprovers::create(
+ const Option<Authorizer*>& authorizer,
+ const Option<Principal>& principal,
+ std::initializer_list<authorization::Action> actions)
+{
+ // Ensures there are no repeated elements.
+ hashset<authorization::Action> _actions(actions);
+
+ Option<authorization::Subject> subject =
+ authorization::createSubject(principal);
+
+ if (authorizer.isNone()) {
+ hashmap<authorization::Action, Owned<ObjectApprover>> approvers;
+
+ foreach (authorization::Action action, _actions) {
+ approvers.put(
+ action,
+ Owned<ObjectApprover>(new AcceptingObjectApprover()));
+ }
+
+ return Owned<ObjectApprovers>(
+ new ObjectApprovers(std::move(approvers), principal));
+ }
+
+ return process::collect(lambda::map<std::list>(
+ [&](authorization::Action action) -> Future<Owned<ObjectApprover>> {
+ return authorizer.get()->getObjectApprover(subject, action);
+ },
+ _actions))
+ .then([=](const std::list<Owned<ObjectApprover>>& _approvers) {
+ return Owned<ObjectApprovers>(
+ new ObjectApprovers(lambda::zip(_actions, _approvers), principal));
+ });
+}
+
bool approveViewFrameworkInfo(
const Owned<ObjectApprover>& frameworksApprover,
http://git-wip-us.apache.org/repos/asf/mesos/blob/dc9eaeb2/src/common/http.hpp
----------------------------------------------------------------------
diff --git a/src/common/http.hpp b/src/common/http.hpp
index 750d3bf..d92ae2b 100644
--- a/src/common/http.hpp
+++ b/src/common/http.hpp
@@ -26,6 +26,7 @@
#include <mesos/quota/quota.hpp>
+#include <process/authenticator.hpp>
#include <process/future.hpp>
#include <process/http.hpp>
#include <process/owned.hpp>
@@ -37,6 +38,28 @@
#include <stout/protobuf.hpp>
#include <stout/unreachable.hpp>
+// TODO(benh): Remove this once we get C++14 as an enum should have a
+// default hash.
+namespace std {
+
+template <>
+struct hash<mesos::authorization::Action>
+{
+ typedef size_t result_type;
+
+ typedef mesos::authorization::Action argument_type;
+
+ result_type operator()(const argument_type& action) const
+ {
+ size_t seed = 0;
+ boost::hash_combine(
+ seed, static_cast<std::underlying_type<argument_type>::type>(action));
+ return seed;
+ }
+};
+
+} // namespace std {
+
namespace mesos {
class Attributes;
@@ -164,6 +187,85 @@ public:
};
+class ObjectApprovers
+{
+public:
+ static process::Future<process::Owned<ObjectApprovers>> create(
+ const Option<Authorizer*>& authorizer,
+ const Option<process::http::authentication::Principal>& principal,
+ std::initializer_list<authorization::Action> actions);
+
+ template <authorization::Action action, typename... Args>
+ bool approved(const Args&... args)
+ {
+ if (!approvers.contains(action)) {
+ LOG(WARNING) << "Attempted to authorize "
+ << (principal.isSome()
+ ? "'" + stringify(principal.get()) + "'"
+ : "")
+ << " for unexpected action " << stringify(action);
+ return false;
+ }
+
+ Try<bool> approved = approvers[action]->approved(
+ ObjectApprover::Object(args...));
+
+ if (approved.isError()) {
+ // TODO(joerg84): Expose these errors back to the caller.
+ LOG(WARNING) << "Failed to authorize principal "
+ << (principal.isSome()
+ ? "'" + stringify(principal.get()) + "' "
+ : "")
+ << "for action " << stringify(action) << ": "
+ << approved.error();
+ return false;
+ }
+
+ return approved.get();
+ }
+
+private:
+ ObjectApprovers(
+ hashmap<
+ authorization::Action,
+ process::Owned<ObjectApprover>>&& _approvers,
+ const Option<process::http::authentication::Principal>& _principal)
+ : approvers(std::move(_approvers)), principal(_principal) {}
+
+ hashmap<authorization::Action, process::Owned<ObjectApprover>> approvers;
+ Option<process::http::authentication::Principal> principal;
+};
+
+
+template <>
+inline bool ObjectApprovers::approved<authorization::VIEW_ROLE>(
+ const Resource& resource)
+{
+ // Necessary because recovered agents are presented in old format.
+ if (resource.has_role() && resource.role() != "*" &&
+ !approved<authorization::VIEW_ROLE>(resource.role())) {
+ return false;
+ }
+
+ // Reservations follow a path model where each entry is a child of the
+ // previous one. Therefore, to accept the resource the acceptor has to
+ // accept all entries.
+ foreach (Resource::ReservationInfo reservation, resource.reservations()) {
+ if (!approved<authorization::VIEW_ROLE>(reservation.role())) {
+ return false;
+ }
+ }
+
+ if (resource.has_allocation_info() &&
+ !approved<authorization::VIEW_ROLE>(
+ resource.allocation_info().role())) {
+ return false;
+ }
+
+ return true;
+}
+
+
// Determines which objects will be accepted based on authorization.
class AuthorizationAcceptor
{
@@ -273,6 +375,7 @@ bool approveViewRole(
const process::Owned<ObjectApprover>& rolesApprover,
const std::string& role);
+
// Authorizes resources in either the pre- or the post-reservation-refinement
// formats.
// TODO(arojas): Update this helper to only accept the