Added filtering to /slaves, /containers and /frameworks endpoints. Added query parameter support for the '/slaves', '/frameworks' and '/containers' endpoints.
This allows slaves, frameworks and containers to be queried by ID. If no ID is specified, all records are returned, consistent with current behavior. Review: https://reviews.apache.org/r/60822/ Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/8363449c Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/8363449c Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/8363449c Branch: refs/heads/master Commit: 8363449c130298b9c77560c5df583dc1226dd17c Parents: aa244ba Author: Quinn Leng <quinn.leng....@gmail.com> Authored: Tue Jul 18 17:06:59 2017 -0700 Committer: Greg Mann <gregorywm...@gmail.com> Committed: Tue Jul 18 17:08:43 2017 -0700 ---------------------------------------------------------------------- src/master/http.cpp | 445 +++++++++++++++++++++++------------------------ src/slave/http.cpp | 96 +++++----- src/slave/http.hpp | 3 +- 3 files changed, 265 insertions(+), 279 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/8363449c/src/master/http.cpp ---------------------------------------------------------------------- diff --git a/src/master/http.cpp b/src/master/http.cpp index cbe6d96..9df086c 100644 --- a/src/master/http.cpp +++ b/src/master/http.cpp @@ -219,11 +219,11 @@ static void json(JSON::ObjectWriter* writer, const Summary<Framework>& summary); // user is authorized to view them. struct FullFrameworkWriter { FullFrameworkWriter( - const Owned<ObjectApprover>& taskApprover, - const Owned<ObjectApprover>& executorApprover, + const Owned<AuthorizationAcceptor>& authorizeTask, + const Owned<AuthorizationAcceptor>& authorizeExecutorInfo, const Framework* framework) - : taskApprover_(taskApprover), - executorApprover_(executorApprover), + : authorizeTask_(authorizeTask), + authorizeExecutorInfo_(authorizeExecutorInfo), framework_(framework) {} void operator()(JSON::ObjectWriter* writer) const @@ -268,7 +268,7 @@ struct FullFrameworkWriter { writer->field("tasks", [this](JSON::ArrayWriter* writer) { foreachvalue (const TaskInfo& taskInfo, framework_->pendingTasks) { // Skip unauthorized tasks. - if (!approveViewTaskInfo(taskApprover_, taskInfo, framework_->info)) { + if (!authorizeTask_->accept(taskInfo, framework_->info)) { continue; } @@ -309,7 +309,7 @@ struct FullFrameworkWriter { foreachvalue (Task* task, framework_->tasks) { // Skip unauthorized tasks. - if (!approveViewTask(taskApprover_, *task, framework_->info)) { + if (!authorizeTask_->accept(*task, framework_->info)) { continue; } @@ -320,7 +320,7 @@ struct FullFrameworkWriter { writer->field("unreachable_tasks", [this](JSON::ArrayWriter* writer) { foreachvalue (const Owned<Task>& task, framework_->unreachableTasks) { // Skip unauthorized tasks. - if (!approveViewTask(taskApprover_, *task.get(), framework_->info)) { + if (!authorizeTask_->accept(*task.get(), framework_->info)) { continue; } @@ -331,7 +331,7 @@ struct FullFrameworkWriter { writer->field("completed_tasks", [this](JSON::ArrayWriter* writer) { foreach (const Owned<Task>& task, framework_->completedTasks) { // Skip unauthorized tasks. - if (!approveViewTask(taskApprover_, *task.get(), framework_->info)) { + if (!authorizeTask_->accept(*task.get(), framework_->info)) { continue; } @@ -357,10 +357,7 @@ struct FullFrameworkWriter { &executor, &slaveId](JSON::ObjectWriter* writer) { // Skip unauthorized executors. - if (!approveViewExecutorInfo( - executorApprover_, - executor, - framework_->info)) { + if (!authorizeExecutorInfo_->accept(executor, framework_->info)) { return; } @@ -377,16 +374,18 @@ struct FullFrameworkWriter { } } - const Owned<ObjectApprover>& taskApprover_; - const Owned<ObjectApprover>& executorApprover_; + const Owned<AuthorizationAcceptor>& authorizeTask_; + const Owned<AuthorizationAcceptor>& authorizeExecutorInfo_; const Framework* framework_; }; struct SlaveWriter { - SlaveWriter(const Slave& slave, const Owned<ObjectApprover>& roleApprover) - : slave_(slave), roleApprover_(roleApprover) {} + SlaveWriter( + const Slave& slave, + const Owned<AuthorizationAcceptor>& authorizeRole) + : slave_(slave), authorizeRole_(authorizeRole) {} void operator()(JSON::ObjectWriter* writer) const { @@ -411,7 +410,7 @@ struct SlaveWriter // TODO(arojas): Consider showing unapproved resources in an // aggregated special field, so that all resource values add up // MESOS-7779. - if (approveViewRole(roleApprover_, role)) { + if (authorizeRole_->accept(role)) { writer->field(role, reservation); } } @@ -424,7 +423,7 @@ struct SlaveWriter } const Slave& slave_; - const Owned<ObjectApprover>& roleApprover_; + const Owned<AuthorizationAcceptor>& authorizeRole_; }; @@ -432,14 +431,20 @@ struct SlavesWriter { SlavesWriter( const Master::Slaves& slaves, - const Owned<ObjectApprover>& roleApprover) + const Owned<AuthorizationAcceptor>& authorizeRole, + const IDAcceptor<SlaveID>& selectSlaveId) : slaves_(slaves), - roleApprover_(roleApprover) {} + authorizeRole_(authorizeRole), + selectSlaveId_(selectSlaveId) {} void operator()(JSON::ObjectWriter* writer) const { writer->field("slaves", [this](JSON::ArrayWriter* writer) { foreachvalue (const Slave* slave, slaves_.registered) { + if (!selectSlaveId_.accept(slave->id)) { + continue; + } + writer->element([this, &slave](JSON::ObjectWriter* writer) { writeSlave(slave, writer); }); @@ -448,6 +453,10 @@ struct SlavesWriter writer->field("recovered_slaves", [this](JSON::ArrayWriter* writer) { foreachvalue (const SlaveInfo& slaveInfo, slaves_.recovered) { + if (!selectSlaveId_.accept(slaveInfo.id())) { + continue; + } + writer->element([&slaveInfo](JSON::ObjectWriter* writer) { json(writer, slaveInfo); }); @@ -457,7 +466,7 @@ struct SlavesWriter void writeSlave(const Slave* slave, JSON::ObjectWriter* writer) const { - SlaveWriter(*slave, roleApprover_)(writer); + SlaveWriter(*slave, authorizeRole_)(writer); // Add the complete protobuf->JSON for all used, reserved, // and offered resources. The other endpoints summarize @@ -474,7 +483,7 @@ struct SlavesWriter foreachpair (const string& role, const Resources& resources, reserved) { - if (approveViewRole(roleApprover_, role)) { + if (authorizeRole_->accept(role)) { writer->field(role, [&resources](JSON::ArrayWriter* writer) { foreach (Resource resource, resources) { convertResourceFormat(&resource, ENDPOINT); @@ -502,9 +511,8 @@ struct SlavesWriter "used_resources_full", [&usedResources, this](JSON::ArrayWriter* writer) { foreach (Resource resource, usedResources) { - if (approveViewRole(roleApprover_, resource.role()) && - approveViewRole(roleApprover_, - resource.allocation_info().role())) { + if (authorizeRole_->accept(resource.role()) && + authorizeRole_->accept(resource.allocation_info().role())) { convertResourceFormat(&resource, ENDPOINT); writer->element(JSON::Protobuf(resource)); } @@ -517,7 +525,7 @@ struct SlavesWriter "offered_resources_full", [&offeredResources, this](JSON::ArrayWriter* writer) { foreach (Resource resource, offeredResources) { - if (approveViewRole(roleApprover_, resource.role())) { + if (authorizeRole_->accept(resource.role())) { convertResourceFormat(&resource, ENDPOINT); writer->element(JSON::Protobuf(resource)); } @@ -525,8 +533,9 @@ struct SlavesWriter }); } - const Master::Slaves &slaves_; - const Owned<ObjectApprover> &roleApprover_; + const Master::Slaves& slaves_; + const Owned<AuthorizationAcceptor>& authorizeRole_; + const IDAcceptor<SlaveID>& selectSlaveId_; }; @@ -1467,7 +1476,11 @@ string Master::Http::FRAMEWORKS_HELP() "current master is not the leader.", "", "Returns 503 SERVICE_UNAVAILABLE if the leading master cannot be", - "found."), + "found.", + "", + "Query parameters:", + "> framework_id=VALUE The ID of the framework returned " + "(when no framework ID specified, all frameworks will be returned)."), AUTHENTICATION(true), AUTHORIZATION( "This endpoint might be filtered based on the user accessing it.", @@ -1493,87 +1506,89 @@ Future<Response> Master::Http::frameworks( return redirect(request); } - // Retrieve `ObjectApprover`s for authorizing frameworks and tasks and - // executors. - Future<Owned<ObjectApprover>> frameworksApprover; - Future<Owned<ObjectApprover>> tasksApprover; - Future<Owned<ObjectApprover>> executorsApprover; - - if (master->authorizer.isSome()) { - Option<authorization::Subject> subject = createSubject(principal); - - frameworksApprover = master->authorizer.get()->getObjectApprover( - subject, authorization::VIEW_FRAMEWORK); - - tasksApprover = master->authorizer.get()->getObjectApprover( - subject, authorization::VIEW_TASK); - - executorsApprover = master->authorizer.get()->getObjectApprover( - subject, authorization::VIEW_EXECUTOR); - } else { - frameworksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover()); - tasksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover()); - executorsApprover = Owned<ObjectApprover>(new AcceptingObjectApprover()); - } + Future<Owned<AuthorizationAcceptor>> authorizeFrameworkInfo = + AuthorizationAcceptor::create( + principal, master->authorizer, authorization::VIEW_FRAMEWORK); + Future<Owned<AuthorizationAcceptor>> authorizeTask = + AuthorizationAcceptor::create( + principal, master->authorizer, authorization::VIEW_TASK); + Future<Owned<AuthorizationAcceptor>> authorizeExecutorInfo = + AuthorizationAcceptor::create( + principal, master->authorizer, authorization::VIEW_EXECUTOR); + Future<IDAcceptor<FrameworkID>> selectFrameworkId = + IDAcceptor<FrameworkID>(request.url.query.get("framework_id")); - return collect(frameworksApprover, tasksApprover, executorsApprover) + return collect( + authorizeFrameworkInfo, + authorizeTask, + authorizeExecutorInfo, + selectFrameworkId) .then(defer(master->self(), - [this, request](const tuple<Owned<ObjectApprover>, - Owned<ObjectApprover>, - Owned<ObjectApprover>>& approvers) + [this, request](const tuple<Owned<AuthorizationAcceptor>, + Owned<AuthorizationAcceptor>, + Owned<AuthorizationAcceptor>, + IDAcceptor<FrameworkID>>& acceptors) -> Response { // This lambda is consumed before the outer lambda // returns, hence capture by reference is fine here. - auto frameworks = [this, &approvers](JSON::ObjectWriter* writer) { - // Get approver from tuple. - Owned<ObjectApprover> frameworksApprover; - Owned<ObjectApprover> tasksApprover; - Owned<ObjectApprover> executorsApprover; - tie(frameworksApprover, tasksApprover, executorsApprover) = approvers; + auto frameworks = [this, &acceptors](JSON::ObjectWriter* writer) { + Owned<AuthorizationAcceptor> authorizeFrameworkInfo; + Owned<AuthorizationAcceptor> authorizeTask; + Owned<AuthorizationAcceptor> authorizeExecutorInfo; + IDAcceptor<FrameworkID> selectFrameworkId; + tie(authorizeFrameworkInfo, + authorizeTask, + authorizeExecutorInfo, + selectFrameworkId) = acceptors; // Model all of the frameworks. writer->field( "frameworks", - [this, &frameworksApprover, &executorsApprover, &tasksApprover]( - JSON::ArrayWriter* writer) { - foreachvalue (Framework* framework, - master->frameworks.registered) { - // Skip unauthorized frameworks. - if (!approveViewFrameworkInfo( - frameworksApprover, framework->info)) { - continue; - } + [this, + &authorizeFrameworkInfo, + &authorizeTask, + &authorizeExecutorInfo, + &selectFrameworkId](JSON::ArrayWriter* writer) { + foreachvalue (Framework* framework, master->frameworks.registered) { + // Skip unauthorized frameworks or frameworks without a matching ID. + if (!selectFrameworkId.accept(framework->id()) || + !authorizeFrameworkInfo->accept(framework->info)) { + continue; + } - FullFrameworkWriter frameworkWriter( - tasksApprover, - executorsApprover, - framework); + FullFrameworkWriter frameworkWriter( + authorizeTask, + authorizeExecutorInfo, + framework); - writer->element(frameworkWriter); - } - }); + writer->element(frameworkWriter); + } + }); // Model all of the completed frameworks. writer->field( "completed_frameworks", - [this, &frameworksApprover, &executorsApprover, &tasksApprover]( - JSON::ArrayWriter* writer) { - foreachvalue (const Owned<Framework>& framework, - master->frameworks.completed) { - // Skip unauthorized frameworks. - if (!approveViewFrameworkInfo( - frameworksApprover, framework->info)) { - continue; - } + [this, + &authorizeFrameworkInfo, + &authorizeTask, + &authorizeExecutorInfo, + &selectFrameworkId](JSON::ArrayWriter* writer) { + foreachvalue (const Owned<Framework>& framework, + master->frameworks.completed) { + // Skip unauthorized frameworks or frameworks without a matching ID. + if (!selectFrameworkId.accept(framework->id()) || + !authorizeFrameworkInfo->accept(framework->info)) { + continue; + } - FullFrameworkWriter frameworkWriter( - tasksApprover, - executorsApprover, - framework.get()); + FullFrameworkWriter frameworkWriter( + authorizeTask, + authorizeExecutorInfo, + framework.get()); - writer->element(frameworkWriter); - } - }); + writer->element(frameworkWriter); + } + }); // Unregistered frameworks are no longer possible. We emit an // empty array for the sake of backward compatibility. @@ -2433,7 +2448,11 @@ string Master::Http::SLAVES_HELP() "", "This endpoint shows information about the agents which are registered", "in this master or recovered from registry, formatted as a JSON", - "object."), + "object.", + "", + "Query parameters:", + "> slave_id=VALUE The ID of the slave returned " + "(when no slave_id is specified, all slaves will be returned)."), AUTHENTICATION(true)); } @@ -2447,26 +2466,28 @@ Future<Response> Master::Http::slaves( return redirect(request); } - // Retrieve `ObjectApprover`s for authorizing roles. - Future<Owned<ObjectApprover>> rolesApprover; - - if (master->authorizer.isSome()) { - Option<authorization::Subject> subject = createSubject(principal); - - rolesApprover = master->authorizer.get()->getObjectApprover( - subject, authorization::VIEW_ROLE); - } else { - rolesApprover = Owned<ObjectApprover>(new AcceptingObjectApprover()); - } + Future<Owned<AuthorizationAcceptor>> authorizeRole = + AuthorizationAcceptor::create( + principal, master->authorizer, authorization::VIEW_ROLE); + Future<IDAcceptor<SlaveID>> selectSlaveId = + IDAcceptor<SlaveID>(request.url.query.get("slave_id")); Master* master = this->master; Option<string> jsonp = request.url.query.get("jsonp"); - return rolesApprover.then(defer(master->self(), - [master, jsonp](const Owned<ObjectApprover>& rolesApprover) + return collect(authorizeRole, selectSlaveId) + .then(defer(master->self(), + [master, jsonp](const tuple<Owned<AuthorizationAcceptor>, + IDAcceptor<SlaveID>>& acceptors) -> Future<Response> { - return OK(jsonify(SlavesWriter(master->slaves, rolesApprover)), jsonp); - })); + Owned<AuthorizationAcceptor> authorizeRole; + IDAcceptor<SlaveID> selectSlaveId; + tie(authorizeRole, selectSlaveId) = acceptors; + + return OK( + jsonify(SlavesWriter(master->slaves, authorizeRole, selectSlaveId)), + jsonp); + })); } @@ -2745,66 +2766,49 @@ Future<Response> Master::Http::state( return redirect(request); } - // Retrieve `ObjectApprover`s for authorizing frameworks and tasks. - Future<Owned<ObjectApprover>> rolesApprover; - Future<Owned<ObjectApprover>> frameworksApprover; - Future<Owned<ObjectApprover>> tasksApprover; - Future<Owned<ObjectApprover>> executorsApprover; - Future<Owned<ObjectApprover>> flagsApprover; - - if (master->authorizer.isSome()) { - Option<authorization::Subject> subject = createSubject(principal); - - rolesApprover = master->authorizer.get()->getObjectApprover( - subject, authorization::VIEW_ROLE); - - frameworksApprover = master->authorizer.get()->getObjectApprover( - subject, authorization::VIEW_FRAMEWORK); - - tasksApprover = master->authorizer.get()->getObjectApprover( - subject, authorization::VIEW_TASK); - - executorsApprover = master->authorizer.get()->getObjectApprover( - subject, authorization::VIEW_EXECUTOR); - - flagsApprover = master->authorizer.get()->getObjectApprover( - subject, authorization::VIEW_FLAGS); - } else { - rolesApprover = Owned<ObjectApprover>(new AcceptingObjectApprover()); - frameworksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover()); - tasksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover()); - executorsApprover = Owned<ObjectApprover>(new AcceptingObjectApprover()); - flagsApprover = Owned<ObjectApprover>(new AcceptingObjectApprover()); - } + Future<Owned<AuthorizationAcceptor>> authorizeRole = + AuthorizationAcceptor::create( + principal, master->authorizer, authorization::VIEW_ROLE); + Future<Owned<AuthorizationAcceptor>> authorizeFrameworkInfo = + AuthorizationAcceptor::create( + principal, master->authorizer, authorization::VIEW_FRAMEWORK); + Future<Owned<AuthorizationAcceptor>> authorizeTask = + AuthorizationAcceptor::create( + principal, master->authorizer, authorization::VIEW_TASK); + Future<Owned<AuthorizationAcceptor>> authorizeExecutorInfo = + AuthorizationAcceptor::create( + principal, master->authorizer, authorization::VIEW_EXECUTOR); + Future<Owned<AuthorizationAcceptor>> authorizeFlags = + AuthorizationAcceptor::create( + principal, master->authorizer, authorization::VIEW_FLAGS); return collect( - rolesApprover, - frameworksApprover, - tasksApprover, - executorsApprover, - flagsApprover) + authorizeRole, + authorizeFrameworkInfo, + authorizeTask, + authorizeExecutorInfo, + authorizeFlags) .then(defer( master->self(), - [this, request](const tuple<Owned<ObjectApprover>, - Owned<ObjectApprover>, - Owned<ObjectApprover>, - Owned<ObjectApprover>, - Owned<ObjectApprover>>& approvers) + [this, request](const tuple<Owned<AuthorizationAcceptor>, + Owned<AuthorizationAcceptor>, + Owned<AuthorizationAcceptor>, + Owned<AuthorizationAcceptor>, + Owned<AuthorizationAcceptor>>& acceptors) -> Response { // This lambda is consumed before the outer lambda // returns, hence capture by reference is fine here. - auto state = [this, &approvers](JSON::ObjectWriter* writer) { - // Get approver from tuple. - Owned<ObjectApprover> rolesApprover; - Owned<ObjectApprover> frameworksApprover; - Owned<ObjectApprover> tasksApprover; - Owned<ObjectApprover> executorsApprover; - Owned<ObjectApprover> flagsApprover; - tie(rolesApprover, - frameworksApprover, - tasksApprover, - executorsApprover, - flagsApprover) = approvers; + auto state = [this, &acceptors](JSON::ObjectWriter* writer) { + Owned<AuthorizationAcceptor> authorizeRole; + Owned<AuthorizationAcceptor> authorizeFrameworkInfo; + Owned<AuthorizationAcceptor> authorizeTask; + Owned<AuthorizationAcceptor> authorizeExecutorInfo; + Owned<AuthorizationAcceptor> authorizeFlags; + tie(authorizeRole, + authorizeFrameworkInfo, + authorizeTask, + authorizeExecutorInfo, + authorizeFlags) = acceptors; writer->field("version", MESOS_VERSION); @@ -2851,7 +2855,7 @@ Future<Response> Master::Http::state( }); } - if (approveViewFlags(flagsApprover)) { + if (authorizeFlags->accept()) { if (master->flags.cluster.isSome()) { writer->field("cluster", master->flags.cluster.get()); } @@ -2877,9 +2881,9 @@ Future<Response> Master::Http::state( // Model all of the registered slaves. writer->field("slaves", - [this, rolesApprover](JSON::ArrayWriter* writer) { + [this, &authorizeRole](JSON::ArrayWriter* writer) { foreachvalue (Slave* slave, master->slaves.registered) { - writer->element(SlaveWriter(*slave, rolesApprover)); + writer->element(SlaveWriter(*slave, authorizeRole)); } }); @@ -2895,43 +2899,49 @@ Future<Response> Master::Http::state( // Model all of the frameworks. writer->field( "frameworks", - [this, &frameworksApprover, &executorsApprover, &tasksApprover]( - JSON::ArrayWriter* writer) { - foreachvalue ( - Framework* framework, - master->frameworks.registered) { - // Skip unauthorized frameworks. - if (!approveViewFrameworkInfo( - frameworksApprover, framework->info)) { - continue; - } + [this, + &authorizeFrameworkInfo, + &authorizeTask, + &authorizeExecutorInfo](JSON::ArrayWriter* writer) { + foreachvalue ( + Framework* framework, + master->frameworks.registered) { + // Skip unauthorized frameworks. + if (!authorizeFrameworkInfo->accept(framework->info)) { + continue; + } - auto frameworkWriter = FullFrameworkWriter( - tasksApprover, executorsApprover, framework); + auto frameworkWriter = FullFrameworkWriter( + authorizeTask, + authorizeExecutorInfo, + framework); - writer->element(frameworkWriter); - } - }); + writer->element(frameworkWriter); + } + }); // Model all of the completed frameworks. writer->field( "completed_frameworks", - [this, &frameworksApprover, &executorsApprover, &tasksApprover]( - JSON::ArrayWriter* writer) { - foreachvalue (const Owned<Framework>& framework, - master->frameworks.completed) { - // Skip unauthorized frameworks. - if (!approveViewFrameworkInfo( - frameworksApprover, framework->info)) { - continue; - } + [this, + &authorizeFrameworkInfo, + &authorizeTask, + &authorizeExecutorInfo](JSON::ArrayWriter* writer) { + foreachvalue (const Owned<Framework>& framework, + master->frameworks.completed) { + // Skip unauthorized frameworks. + if (!authorizeFrameworkInfo->accept(framework->info)) { + continue; + } - auto frameworkWriter = FullFrameworkWriter( - tasksApprover, executorsApprover, framework.get()); + auto frameworkWriter = FullFrameworkWriter( + authorizeTask, + authorizeExecutorInfo, + framework.get()); - writer->element(frameworkWriter); - } - }); + writer->element(frameworkWriter); + } + }); // Orphan tasks are no longer possible. We emit an empty array // for the sake of backward compatibility. @@ -3218,31 +3228,22 @@ Future<Response> Master::Http::stateSummary( return redirect(request); } - Future<Owned<ObjectApprover>> rolesApprover; - Future<Owned<ObjectApprover>> frameworksApprover; - - if (master->authorizer.isSome()) { - Option<authorization::Subject> subject = createSubject(principal); - - rolesApprover = master->authorizer.get()->getObjectApprover( - subject, authorization::VIEW_ROLE); - frameworksApprover = master->authorizer.get()->getObjectApprover( - subject, authorization::VIEW_FRAMEWORK); - } else { - rolesApprover = Owned<ObjectApprover>(new AcceptingObjectApprover()); - frameworksApprover = Owned<ObjectApprover>(new AcceptingObjectApprover()); - } + Future<Owned<AuthorizationAcceptor>> authorizeRole = + AuthorizationAcceptor::create( + principal, master->authorizer, authorization::VIEW_ROLE); + Future<Owned<AuthorizationAcceptor>> authorizeFrameworkInfo = + AuthorizationAcceptor::create( + principal, master->authorizer, authorization::VIEW_FRAMEWORK); - return collect(rolesApprover, frameworksApprover).then(defer( + return collect(authorizeRole, authorizeFrameworkInfo).then(defer( master->self(), - [this, request](const tuple<Owned<ObjectApprover>, - Owned<ObjectApprover>>& approvers) + [this, request](const tuple<Owned<AuthorizationAcceptor>, + Owned<AuthorizationAcceptor>>& acceptors) -> Response { - auto stateSummary = [this, &approvers](JSON::ObjectWriter* writer) { - Owned<ObjectApprover> rolesApprover; - Owned<ObjectApprover> frameworksApprover; - tie(rolesApprover, - frameworksApprover) = approvers; + auto stateSummary = [this, &acceptors](JSON::ObjectWriter* writer) { + Owned<AuthorizationAcceptor> authorizeRole; + Owned<AuthorizationAcceptor> authorizeFrameworkInfo; + tie(authorizeRole, authorizeFrameworkInfo) = acceptors; writer->field("hostname", master->info().hostname()); @@ -3271,14 +3272,14 @@ Future<Response> Master::Http::stateSummary( [this, &slaveFrameworkMapping, &taskStateSummaries, - &rolesApprover](JSON::ArrayWriter* writer) { + &authorizeRole](JSON::ArrayWriter* writer) { foreachvalue (Slave* slave, master->slaves.registered) { writer->element( [&slave, &slaveFrameworkMapping, &taskStateSummaries, - &rolesApprover](JSON::ObjectWriter* writer) { - SlaveWriter slaveWriter(*slave, rolesApprover); + &authorizeRole](JSON::ObjectWriter* writer) { + SlaveWriter slaveWriter(*slave, authorizeRole); slaveWriter(writer); // Add the 'TaskState' summary for this slave. @@ -3326,14 +3327,12 @@ Future<Response> Master::Http::stateSummary( [this, &slaveFrameworkMapping, &taskStateSummaries, - &frameworksApprover](JSON::ArrayWriter* writer) { + &authorizeFrameworkInfo](JSON::ArrayWriter* writer) { foreachpair (const FrameworkID& frameworkId, Framework* framework, master->frameworks.registered) { // Skip unauthorized frameworks. - if (!approveViewFrameworkInfo( - frameworksApprover, - framework->info)) { + if (!authorizeFrameworkInfo->accept(framework->info)) { continue; } http://git-wip-us.apache.org/repos/asf/mesos/blob/8363449c/src/slave/http.cpp ---------------------------------------------------------------------- diff --git a/src/slave/http.cpp b/src/slave/http.cpp index 5824661..2d33f0b 100644 --- a/src/slave/http.cpp +++ b/src/slave/http.cpp @@ -2050,20 +2050,14 @@ Future<Response> Http::getContainers( { CHECK_EQ(mesos::agent::Call::GET_CONTAINERS, call.type()); - Future<Owned<ObjectApprover>> approver; - - if (slave->authorizer.isSome()) { - Option<authorization::Subject> subject = createSubject(principal); - - 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); + Future<Owned<AuthorizationAcceptor>> authorizeContainer = + AuthorizationAcceptor::create( + principal, slave->authorizer, authorization::VIEW_CONTAINER); + + return authorizeContainer.then(defer(slave->self(), + [this](const Owned<AuthorizationAcceptor>& authorizeContainer) { + // Use an empty container ID filter. + return __containers(authorizeContainer, None()); })).then([acceptType](const Future<JSON::Array>& result) -> Future<Response> { if (!result.isReady()) { @@ -2089,22 +2083,23 @@ Future<Response> Http::_containers( const Request& request, const Option<Principal>& principal) const { - Future<Owned<ObjectApprover>> approver; - - if (slave->authorizer.isSome()) { - Option<authorization::Subject> subject = createSubject(principal); - - approver = slave->authorizer.get()->getObjectApprover( - subject, authorization::VIEW_CONTAINER); - } else { - approver = Owned<ObjectApprover>(new AcceptingObjectApprover()); - } + Future<Owned<AuthorizationAcceptor>> authorizeContainer = + AuthorizationAcceptor::create( + principal, slave->authorizer, authorization::VIEW_CONTAINER); + Future<IDAcceptor<ContainerID>> selectContainerId = + IDAcceptor<ContainerID>(request.url.query.get("container_id")); - return approver.then(defer(slave->self(), [this]( - const Owned<ObjectApprover>& approver) { - return __containers(approver); - })) - .then([request](const Future<JSON::Array>& result) -> Future<Response> { + return collect(authorizeContainer, selectContainerId) + .then(defer( + slave->self(), + [this](const tuple<Owned<AuthorizationAcceptor>, + IDAcceptor<ContainerID>>& acceptors) { + Owned<AuthorizationAcceptor> authorizeContainer; + Option<IDAcceptor<ContainerID>> selectContainerId; + tie(authorizeContainer, selectContainerId) = acceptors; + + return __containers(authorizeContainer, selectContainerId); + })).then([request](const Future<JSON::Array>& result) -> Future<Response> { if (!result.isReady()) { LOG(WARNING) << "Could not collect container status and statistics: " << (result.isFailed() @@ -2118,12 +2113,13 @@ Future<Response> Http::_containers( return process::http::OK( result.get(), request.url.query.get("jsonp")); - }); + }); } Future<JSON::Array> Http::__containers( - Option<Owned<ObjectApprover>> approver) const + Owned<AuthorizationAcceptor> authorizeContainer, + Option<IDAcceptor<ContainerID>> selectContainerId) const { Owned<list<JSON::Object>> metadata(new list<JSON::Object>()); list<Future<ContainerStatus>> statusFutures; @@ -2140,32 +2136,22 @@ Future<JSON::Array> Http::__containers( const ExecutorInfo& info = executor->info; const ContainerID& containerId = executor->containerId; - Try<bool> authorized = true; - - if (approver.isSome()) { - ObjectApprover::Object object(info, framework->info); - - authorized = approver.get()->approved(object); - - if (authorized.isError()) { - LOG(WARNING) << "Error during ViewContainer authorization: " - << authorized.error(); - authorized = false; - } + if ((selectContainerId.isSome() && + !selectContainerId->accept(containerId)) || + !authorizeContainer->accept(info, framework->info)) { + continue; } - 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)); - } + 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/8363449c/src/slave/http.hpp ---------------------------------------------------------------------- diff --git a/src/slave/http.hpp b/src/slave/http.hpp index ad412d4..44a95de 100644 --- a/src/slave/http.hpp +++ b/src/slave/http.hpp @@ -114,7 +114,8 @@ private: // Helper function to collect containers status and resource statistics. process::Future<JSON::Array> __containers( - Option<process::Owned<ObjectApprover>> approver) const; + process::Owned<AuthorizationAcceptor> authorizeContainer, + Option<IDAcceptor<ContainerID>> selectContainerId) const; // Helper routines for endpoint authorization. Try<std::string> extractEndpoint(const process::http::URL& url) const;