You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by me...@apache.org on 2016/12/14 03:37:21 UTC
[1/4] mesos git commit: Added authorization actions VIEW_CONTAINERS
and SET_LOG_LEVEL.
Repository: mesos
Updated Branches:
refs/heads/master bf223671a -> 959b97e90
Added authorization actions VIEW_CONTAINERS and SET_LOG_LEVEL.
Adds the authorization action `VIEW_CONTAINERS` which takes an object
of type `FrameworkInfo` and `ExecutorInfo` and optionally a
`CommandInfo`.
It also adds the authorization action `SET_LOG_LEVEL` which takes no
object.
Includes testing for the ACLs and interface.
Review: https://reviews.apache.org/r/54535/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/9ec8b5e9
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/9ec8b5e9
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/9ec8b5e9
Branch: refs/heads/master
Commit: 9ec8b5e9256e3001cfbedb17ca6272dfe31db73a
Parents: bf22367
Author: Alexander Rojas <al...@mesosphere.io>
Authored: Tue Dec 13 17:01:11 2016 -0800
Committer: Adam B <ad...@mesosphere.io>
Committed: Tue Dec 13 17:01:11 2016 -0800
----------------------------------------------------------------------
include/mesos/authorizer/acls.proto | 24 ++++
include/mesos/authorizer/authorizer.proto | 7 ++
src/authorizer/local/authorizer.cpp | 48 ++++++++
src/tests/authorization_tests.cpp | 152 +++++++++++++++++++++++++
4 files changed, 231 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/9ec8b5e9/include/mesos/authorizer/acls.proto
----------------------------------------------------------------------
diff --git a/include/mesos/authorizer/acls.proto b/include/mesos/authorizer/acls.proto
index 3499cac..fd25e54 100644
--- a/include/mesos/authorizer/acls.proto
+++ b/include/mesos/authorizer/acls.proto
@@ -345,6 +345,28 @@ message ACL {
// nested containers can be waited on.
required Entity users = 2;
}
+
+ // Which principals are authorized to see the container metadata of a
+ // container whose executor is running as the given operating system user.
+ message ViewContainer {
+ // Subjects: HTTP Username.
+ required Entity principals = 1;
+
+ // Objects: The list of operating system users (e.g., linux users) whose
+ // container metadata can viewed.
+ required Entity users = 2;
+ }
+
+ // Which principals are authorized to change the log level of the
+ // master/agent.
+ message SetLogLevel {
+ // Subjects: HTTP Username.
+ required Entity principals = 1;
+
+ // Objects: Given implicitly. Use Entity type ANY or NONE to allow or deny
+ // access.
+ required Entity level = 2;
+ }
}
@@ -408,4 +430,6 @@ message ACLs {
launch_nested_container_sessions_under_parent_with_user = 28;
repeated ACL.AttachContainerInput attach_containers_input = 29;
repeated ACL.AttachContainerOutput attach_containers_output = 30;
+ repeated ACL.ViewContainer view_containers = 31;
+ repeated ACL.SetLogLevel set_log_level = 32;
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/9ec8b5e9/include/mesos/authorizer/authorizer.proto
----------------------------------------------------------------------
diff --git a/include/mesos/authorizer/authorizer.proto b/include/mesos/authorizer/authorizer.proto
index b7371cd..8b860a3 100644
--- a/include/mesos/authorizer/authorizer.proto
+++ b/include/mesos/authorizer/authorizer.proto
@@ -174,6 +174,13 @@ enum Action {
// This action will set objects of type `ExecutorInfo` and `FrameworkInfo`.
ATTACH_CONTAINER_OUTPUT = 24;
+
+ // This action will set objects of type `ExecutorInfo` and `FrameworkInfo`.
+ VIEW_CONTAINER = 25;
+
+ // This action will not fill in any object fields, since a principal is
+ // either allowed to change the log level or he is unauthorized.
+ SET_LOG_LEVEL = 26;
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/9ec8b5e9/src/authorizer/local/authorizer.cpp
----------------------------------------------------------------------
diff --git a/src/authorizer/local/authorizer.cpp b/src/authorizer/local/authorizer.cpp
index 3b983d0..b98e1fc 100644
--- a/src/authorizer/local/authorizer.cpp
+++ b/src/authorizer/local/authorizer.cpp
@@ -487,6 +487,26 @@ public:
break;
}
+ case authorization::VIEW_CONTAINER: {
+ aclObject.set_type(mesos::ACL::Entity::ANY);
+
+ if (object->executor_info != nullptr &&
+ object->executor_info->command().has_user()) {
+ aclObject.add_values(object->executor_info->command().user());
+ aclObject.set_type(mesos::ACL::Entity::SOME);
+ } else if (object->framework_info != nullptr &&
+ object->framework_info->has_user()) {
+ aclObject.add_values(object->framework_info->user());
+ aclObject.set_type(mesos::ACL::Entity::SOME);
+ }
+
+ break;
+ }
+ case authorization::SET_LOG_LEVEL: {
+ aclObject.set_type(mesos::ACL::Entity::ANY);
+
+ break;
+ }
case authorization::UNKNOWN:
LOG(WARNING) << "Authorization for action '" << action_
<< "' is not defined and therefore not authorized";
@@ -1005,6 +1025,28 @@ private:
return acls_;
break;
+ case authorization::SET_LOG_LEVEL:
+ foreach (const ACL::SetLogLevel& acl, acls.set_log_level()) {
+ GenericACL acl_;
+ acl_.subjects = acl.principals();
+ acl_.objects = acl.level();
+
+ acls_.push_back(acl_);
+ }
+
+ return acls_;
+ break;
+ case authorization::VIEW_CONTAINER:
+ foreach (const ACL::ViewContainer& acl, acls.view_containers()) {
+ GenericACL acl_;
+ acl_.subjects = acl.principals();
+ acl_.objects = acl.users();
+
+ acls_.push_back(acl_);
+ }
+
+ return acls_;
+ break;
case authorization::LAUNCH_NESTED_CONTAINER_SESSION:
case authorization::LAUNCH_NESTED_CONTAINER:
return Error("Extracting ACLs for launching nested containers requires "
@@ -1079,6 +1121,12 @@ Option<Error> LocalAuthorizer::validate(const ACLs& acls)
}
}
+ foreach (const ACL::SetLogLevel& acl, acls.set_log_level()) {
+ if (acl.level().type() == ACL::Entity::SOME) {
+ return Error("acls.set_log_level type must be either NONE or ANY");
+ }
+ }
+
foreach (const ACL::GetEndpoint& acl, acls.get_endpoints()) {
if (acl.paths().type() == ACL::Entity::SOME) {
foreach (const string& path, acl.paths().values()) {
http://git-wip-us.apache.org/repos/asf/mesos/blob/9ec8b5e9/src/tests/authorization_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/authorization_tests.cpp b/src/tests/authorization_tests.cpp
index f70d60d..42edecc 100644
--- a/src/tests/authorization_tests.cpp
+++ b/src/tests/authorization_tests.cpp
@@ -1919,6 +1919,105 @@ TYPED_TEST(AuthorizationTest, ViewFramework)
}
+// This tests the authorization of requests to ViewContainer.
+TYPED_TEST(AuthorizationTest, ViewContainer)
+{
+ // Setup ACLs.
+ ACLs acls;
+
+ {
+ // "foo" principal can view no containers.
+ mesos::ACL::ViewContainer* acl = acls.add_view_containers();
+ acl->mutable_principals()->add_values("foo");
+ acl->mutable_users()->set_type(mesos::ACL::Entity::NONE);
+ }
+
+ {
+ // "bar" principal can see containers running under user "bar".
+ mesos::ACL::ViewContainer* acl = acls.add_view_containers();
+ acl->mutable_principals()->add_values("bar");
+ acl->mutable_users()->add_values("bar");
+ }
+
+ {
+ // "ops" principal can see all containers.
+ mesos::ACL::ViewContainer* acl = acls.add_view_containers();
+ acl->mutable_principals()->add_values("ops");
+ acl->mutable_users()->set_type(mesos::ACL::Entity::ANY);
+ }
+
+ {
+ // No one else can view any containers.
+ mesos::ACL::ViewContainer* acl = acls.add_view_containers();
+ acl->mutable_principals()->set_type(mesos::ACL::Entity::ANY);
+ acl->mutable_users()->set_type(mesos::ACL::Entity::NONE);
+ }
+
+ // Create an `Authorizer` with the ACLs.
+ Try<Authorizer*> create = TypeParam::create(parameterize(acls));
+ ASSERT_SOME(create);
+ Owned<Authorizer> authorizer(create.get());
+
+ // Create FrameworkInfo with a generic user as object to be authorized.
+ FrameworkInfo frameworkInfo;
+ {
+ frameworkInfo.set_user("user");
+ frameworkInfo.set_name("f");
+ }
+
+ // Create FrameworkInfo with user "bar" as object to be authorized.
+ FrameworkInfo frameworkInfoBar;
+ {
+ frameworkInfoBar.set_user("bar");
+ frameworkInfoBar.set_name("f");
+ }
+
+ // Principal "foo" cannot view containers running with user "user".
+ {
+ authorization::Request request;
+ request.set_action(authorization::VIEW_CONTAINER);
+ request.mutable_subject()->set_value("foo");
+ request.mutable_object()->mutable_framework_info()->MergeFrom(
+ frameworkInfo);
+
+ AWAIT_EXPECT_FALSE(authorizer.get()->authorized(request));
+ }
+
+ // Principal "bar" cannot view containers running with user "user".
+ {
+ authorization::Request request;
+ request.set_action(authorization::VIEW_CONTAINER);
+ request.mutable_subject()->set_value("bar");
+ request.mutable_object()->mutable_framework_info()->MergeFrom(
+ frameworkInfo);
+
+ AWAIT_EXPECT_FALSE(authorizer.get()->authorized(request));
+ }
+
+ // Principal "ops" can view containers running with user "user".
+ {
+ authorization::Request request;
+ request.set_action(authorization::VIEW_CONTAINER);
+ request.mutable_subject()->set_value("ops");
+ request.mutable_object()->mutable_framework_info()->MergeFrom(
+ frameworkInfo);
+
+ AWAIT_EXPECT_TRUE(authorizer.get()->authorized(request));
+ }
+
+ // Principal "bar" can view containers running with user "bar".
+ {
+ authorization::Request request;
+ request.set_action(authorization::VIEW_CONTAINER);
+ request.mutable_subject()->set_value("bar");
+ request.mutable_object()->mutable_framework_info()->MergeFrom(
+ frameworkInfoBar);
+
+ AWAIT_EXPECT_TRUE(authorizer.get()->authorized(request));
+ }
+}
+
+
// This tests the authorization of requests to ViewTasks.
TYPED_TEST(AuthorizationTest, ViewTask)
{
@@ -3825,6 +3924,59 @@ TYPED_TEST(AuthorizationTest, ViewFlags)
}
+TYPED_TEST(AuthorizationTest, SetLogLevel)
+{
+ // Setup ACLs.
+ ACLs acls;
+
+ {
+ // "foo" principal can set log level.
+ mesos::ACL::SetLogLevel* acl = acls.add_set_log_level();
+ acl->mutable_principals()->add_values("foo");
+ acl->mutable_level()->set_type(mesos::ACL::Entity::ANY);
+ }
+
+ {
+ // Nobody else can set log level.
+ mesos::ACL::SetLogLevel* acl = acls.add_set_log_level();
+ acl->mutable_principals()->set_type(mesos::ACL::Entity::ANY);
+ acl->mutable_level()->set_type(mesos::ACL::Entity::NONE);
+ }
+
+ // Create an `Authorizer` with the ACLs.
+ Try<Authorizer*> create = TypeParam::create(parameterize(acls));
+ ASSERT_SOME(create);
+ Owned<Authorizer> authorizer(create.get());
+
+ {
+ authorization::Request request;
+ request.set_action(authorization::SET_LOG_LEVEL);
+ request.mutable_subject()->set_value("foo");
+
+ AWAIT_EXPECT_TRUE(authorizer.get()->authorized(request));
+ }
+
+ {
+ authorization::Request request;
+ request.set_action(authorization::SET_LOG_LEVEL);
+ request.mutable_subject()->set_value("bar");
+ AWAIT_EXPECT_FALSE(authorizer.get()->authorized(request));
+ }
+
+ // Test that no authorizer is created with invalid ACLs.
+ {
+ ACLs invalid;
+
+ mesos::ACL::SetLogLevel* acl = invalid.add_set_log_level();
+ acl->mutable_principals()->add_values("foo");
+ acl->mutable_level()->add_values("yoda");
+
+ Try<Authorizer*> create = TypeParam::create(parameterize(invalid));
+ EXPECT_ERROR(create);
+ }
+}
+
+
// This tests the authorization of ACLs used for unreserve
// operations on dynamically reserved resources.
TYPED_TEST(AuthorizationTest, ValidateEndpoints)
[4/4] mesos git commit: Enabled authorization in SET_LOG_LEVEL API
call.
Posted by me...@apache.org.
Enabled authorization in SET_LOG_LEVEL API call.
Adds the stub which allows only authorized users to change the log
level of Mesos using the HTTP API v1.
Review: https://reviews.apache.org/r/54662/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/959b97e9
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/959b97e9
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/959b97e9
Branch: refs/heads/master
Commit: 959b97e90b17ecefd9f4e4708288f30e94391e2c
Parents: 77b66ba
Author: Alexander Rojas <al...@mesosphere.io>
Authored: Tue Dec 13 17:31:43 2016 -0800
Committer: Adam B <ad...@mesosphere.io>
Committed: Tue Dec 13 17:34:39 2016 -0800
----------------------------------------------------------------------
src/slave/http.cpp | 33 ++++++++++++++++++++++++++++++---
1 file changed, 30 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/959b97e9/src/slave/http.cpp
----------------------------------------------------------------------
diff --git a/src/slave/http.cpp b/src/slave/http.cpp
index 6784fc5..56c2879 100644
--- a/src/slave/http.cpp
+++ b/src/slave/http.cpp
@@ -895,9 +895,36 @@ Future<Response> Slave::Http::setLoggingLevel(
Duration duration =
Nanoseconds(call.set_logging_level().duration().nanoseconds());
- return dispatch(process::logging(), &Logging::set_level, level, duration)
- .then([]() -> Response {
- return OK();
+ Future<Owned<ObjectApprover>> approver;
+
+ if (slave->authorizer.isSome()) {
+ authorization::Subject subject;
+ if (principal.isSome()) {
+ subject.set_value(principal.get());
+ }
+
+ approver = slave->authorizer.get()->getObjectApprover(
+ subject, authorization::SET_LOG_LEVEL);
+ } else {
+ approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
+ }
+
+ return approver.then(
+ [level, duration](
+ const Owned<ObjectApprover>& approver) -> Future<Response> {
+ Try<bool> approved = approver->approved((ObjectApprover::Object()));
+
+ if (approved.isError()) {
+ return InternalServerError(approved.error());
+ } else if (!approved.get()) {
+ return Forbidden();
+ }
+
+ return dispatch(
+ process::logging(), &Logging::set_level, level, duration)
+ .then([]() -> Response {
+ return OK();
+ });
});
}
[2/4] mesos git commit: Enabled fine grained authorization for the
getContainers API Call.
Posted by me...@apache.org.
Enabled fine grained authorization for the getContainers API Call.
Enables fine grained authorization for the v1 API call `GET_CONTAINERS`.
Review: https://reviews.apache.org/r/54538/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/982abdb5
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/982abdb5
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/982abdb5
Branch: refs/heads/master
Commit: 982abdb591f87ccf1748a735af4e2a8a84ab4dbe
Parents: 9ec8b5e
Author: Alexander Rojas <al...@mesosphere.io>
Authored: Tue Dec 13 17:28:12 2016 -0800
Committer: Adam B <ad...@mesosphere.io>
Committed: Tue Dec 13 17:28:24 2016 -0800
----------------------------------------------------------------------
src/slave/http.cpp | 148 ++++++++++++++++++++++++++++++++---------------
src/slave/slave.hpp | 6 +-
2 files changed, 105 insertions(+), 49 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/982abdb5/src/slave/http.cpp
----------------------------------------------------------------------
diff --git a/src/slave/http.cpp b/src/slave/http.cpp
index 8a71ead..0210379 100644
--- a/src/slave/http.cpp
+++ b/src/slave/http.cpp
@@ -1810,12 +1810,12 @@ Future<Response> Slave::Http::containers(
principal)
.then(defer(
slave->self(),
- [this, request](bool authorized) -> Future<Response> {
+ [this, request, principal](bool authorized) -> Future<Response> {
if (!authorized) {
return Forbidden();
}
- return _containers(request);
+ return _containers(request, principal);
}));
}
@@ -1823,54 +1823,90 @@ Future<Response> Slave::Http::containers(
Future<Response> Slave::Http::getContainers(
const agent::Call& call,
ContentType acceptType,
- const Option<string>& printcipal) const
+ const Option<string>& principal) const
{
CHECK_EQ(agent::Call::GET_CONTAINERS, call.type());
- return __containers()
- .then([acceptType](const Future<JSON::Array>& result)
- -> Future<Response> {
- if (!result.isReady()) {
- LOG(WARNING) << "Could not collect container status and statistics: "
- << (result.isFailed()
- ? result.failure()
- : "Discarded");
- return result.isFailed()
- ? InternalServerError(result.failure())
- : InternalServerError();
- }
+ Future<Owned<ObjectApprover>> approver;
- return OK(
- serialize(
- acceptType,
- evolve<v1::agent::Response::GET_CONTAINERS>(result.get())),
- stringify(acceptType));
- });
+ if (slave->authorizer.isSome()) {
+ authorization::Subject subject;
+ if (principal.isSome()) {
+ subject.set_value(principal.get());
+ }
+
+ approver = slave->authorizer.get()->getObjectApprover(
+ subject, authorization::VIEW_CONTAINER);
+ } else {
+ approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
+ }
+
+ return approver.then(defer(slave->self(), [this](
+ const Owned<ObjectApprover>& approver) {
+ return __containers(approver);
+ })).then([acceptType](const Future<JSON::Array>& result)
+ -> Future<Response> {
+ if (!result.isReady()) {
+ LOG(WARNING) << "Could not collect container status and statistics: "
+ << (result.isFailed()
+ ? result.failure()
+ : "Discarded");
+ return result.isFailed()
+ ? InternalServerError(result.failure())
+ : InternalServerError();
+ }
+
+ return OK(
+ serialize(
+ acceptType,
+ evolve<v1::agent::Response::GET_CONTAINERS>(result.get())),
+ stringify(acceptType));
+ });
}
-Future<Response> Slave::Http::_containers(const Request& request) const
+Future<Response> Slave::Http::_containers(
+ const Request& request,
+ const Option<string>& principal) const
{
- return __containers()
- .then([request](const Future<JSON::Array>& result) -> Future<Response> {
- if (!result.isReady()) {
- LOG(WARNING) << "Could not collect container status and statistics: "
- << (result.isFailed()
- ? result.failure()
- : "Discarded");
-
- return result.isFailed()
- ? InternalServerError(result.failure())
- : InternalServerError();
- }
+ Future<Owned<ObjectApprover>> approver;
- return process::http::OK(
- result.get(), request.url.query.get("jsonp"));
- });
+ if (slave->authorizer.isSome()) {
+ authorization::Subject subject;
+ if (principal.isSome()) {
+ subject.set_value(principal.get());
+ }
+
+ approver = slave->authorizer.get()->getObjectApprover(
+ subject, authorization::VIEW_CONTAINER);
+ } else {
+ approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
+ }
+
+ return approver.then(defer(slave->self(), [this](
+ const Owned<ObjectApprover>& approver) {
+ return __containers(approver);
+ }))
+ .then([request](const Future<JSON::Array>& result) -> Future<Response> {
+ if (!result.isReady()) {
+ LOG(WARNING) << "Could not collect container status and statistics: "
+ << (result.isFailed()
+ ? result.failure()
+ : "Discarded");
+
+ return result.isFailed()
+ ? InternalServerError(result.failure())
+ : InternalServerError();
+ }
+
+ return process::http::OK(
+ result.get(), request.url.query.get("jsonp"));
+ });
}
-Future<JSON::Array> Slave::Http::__containers() const
+Future<JSON::Array> Slave::Http::__containers(
+ Option<Owned<ObjectApprover>> approver) const
{
Owned<list<JSON::Object>> metadata(new list<JSON::Object>());
list<Future<ContainerStatus>> statusFutures;
@@ -1887,16 +1923,34 @@ Future<JSON::Array> Slave::Http::__containers() const
const ExecutorInfo& info = executor->info;
const ContainerID& containerId = executor->containerId;
- JSON::Object entry;
- entry.values["framework_id"] = info.framework_id().value();
- entry.values["executor_id"] = info.executor_id().value();
- entry.values["executor_name"] = info.name();
- entry.values["source"] = info.source();
- entry.values["container_id"] = containerId.value();
+ Try<bool> authorized = true;
- metadata->push_back(entry);
- statusFutures.push_back(slave->containerizer->status(containerId));
- statsFutures.push_back(slave->containerizer->usage(containerId));
+ if (approver.isSome()) {
+ ObjectApprover::Object object;
+ object.executor_info = &info;
+ object.framework_info = &(framework->info);
+
+ authorized = approver.get()->approved(object);
+
+ if (authorized.isError()) {
+ LOG(WARNING) << "Error during ViewContainer authorization: "
+ << authorized.error();
+ authorized = false;
+ }
+ }
+
+ if (authorized.get()) {
+ JSON::Object entry;
+ entry.values["framework_id"] = info.framework_id().value();
+ entry.values["executor_id"] = info.executor_id().value();
+ entry.values["executor_name"] = info.name();
+ entry.values["source"] = info.source();
+ entry.values["container_id"] = containerId.value();
+
+ metadata->push_back(entry);
+ statusFutures.push_back(slave->containerizer->status(containerId));
+ statsFutures.push_back(slave->containerizer->usage(containerId));
+ }
}
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/982abdb5/src/slave/slave.hpp
----------------------------------------------------------------------
diff --git a/src/slave/slave.hpp b/src/slave/slave.hpp
index 059eb77..be72ba9 100644
--- a/src/slave/slave.hpp
+++ b/src/slave/slave.hpp
@@ -545,10 +545,12 @@ private:
// Continuation for `/containers` endpoint
process::Future<process::http::Response> _containers(
- const process::http::Request& request) const;
+ const process::http::Request& request,
+ const Option<std::string>& principal) const;
// Helper function to collect containers status and resource statistics.
- process::Future<JSON::Array> __containers() const;
+ process::Future<JSON::Array> __containers(
+ Option<process::Owned<ObjectApprover>> approver) const;
// Helper routines for endpoint authorization.
Try<std::string> extractEndpoint(const process::http::URL& url) const;
[3/4] mesos git commit: Enabled authorization for the GET_FLAGS API
Call.
Posted by me...@apache.org.
Enabled authorization for the GET_FLAGS API Call.
Adds the stub which allows for restriction of users when attempting
to access the `GET_FLAGS` API v1 call.
Review: https://reviews.apache.org/r/54661/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/77b66ba1
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/77b66ba1
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/77b66ba1
Branch: refs/heads/master
Commit: 77b66ba1b4826ce5f84f675ad2363b8bc3b5d73f
Parents: 982abdb
Author: Alexander Rojas <al...@mesosphere.io>
Authored: Tue Dec 13 17:29:13 2016 -0800
Committer: Adam B <ad...@mesosphere.io>
Committed: Tue Dec 13 17:30:26 2016 -0800
----------------------------------------------------------------------
src/slave/http.cpp | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/77b66ba1/src/slave/http.cpp
----------------------------------------------------------------------
diff --git a/src/slave/http.cpp b/src/slave/http.cpp
index 0210379..6784fc5 100644
--- a/src/slave/http.cpp
+++ b/src/slave/http.cpp
@@ -755,9 +755,36 @@ Future<Response> Slave::Http::getFlags(
{
CHECK_EQ(agent::Call::GET_FLAGS, call.type());
- return OK(serialize(acceptType,
- evolve<v1::agent::Response::GET_FLAGS>(_flags())),
+ Future<Owned<ObjectApprover>> approver;
+
+ if (slave->authorizer.isSome()) {
+ authorization::Subject subject;
+ if (principal.isSome()) {
+ subject.set_value(principal.get());
+ }
+
+ approver = slave->authorizer.get()->getObjectApprover(
+ subject, authorization::VIEW_FLAGS);
+ } else {
+ approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
+ }
+
+ return approver.then(defer(slave->self(),
+ [this, acceptType](
+ const Owned<ObjectApprover>& approver) -> Future<Response> {
+ Try<bool> approved = approver->approved(ObjectApprover::Object());
+
+ if (approved.isError()) {
+ return InternalServerError(approved.error());
+ } else if (!approved.get()) {
+ return Forbidden();
+ }
+
+ return OK(
+ serialize(
+ acceptType, evolve<v1::agent::Response::GET_FLAGS>(_flags())),
stringify(acceptType));
+ }));
}