You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by gi...@apache.org on 2017/12/31 12:24:39 UTC
[3/3] mesos git commit: Added authorization for prune images API call.
Added authorization for prune images API call.
Review: https://reviews.apache.org/r/64864/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/4beb46db
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/4beb46db
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/4beb46db
Branch: refs/heads/1.5.x
Commit: 4beb46db5a54e495212754a672daf81853a57e06
Parents: f023091
Author: Zhitao Li <zh...@gmail.com>
Authored: Sun Dec 31 18:27:44 2017 +0800
Committer: Gilbert Song <so...@gmail.com>
Committed: Sun Dec 31 20:24:29 2017 +0800
----------------------------------------------------------------------
include/mesos/authorizer/acls.proto | 14 ++++++
include/mesos/authorizer/authorizer.proto | 4 ++
src/authorizer/local/authorizer.cpp | 20 +++++++++
src/slave/http.cpp | 60 +++++++++++++++++---------
4 files changed, 78 insertions(+), 20 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/4beb46db/include/mesos/authorizer/acls.proto
----------------------------------------------------------------------
diff --git a/include/mesos/authorizer/acls.proto b/include/mesos/authorizer/acls.proto
index 5c7ed34..152410f 100644
--- a/include/mesos/authorizer/acls.proto
+++ b/include/mesos/authorizer/acls.proto
@@ -495,6 +495,19 @@ message ACL {
// SOME resource provider types and names.
required Entity resource_providers = 2;
}
+
+ // Which principals are authorized to prune unused container images.
+ message PruneImages {
+ // Subjects: HTTP Username.
+ required Entity principals = 1;
+
+ // Objects: Given implicitly.
+ // Use Entity type ANY or NONE to allow or deny access.
+ //
+ // TODO(zhitao): Consider allowing granular permission to act upon
+ // SOME image reference.
+ required Entity images = 2;
+ }
}
@@ -572,4 +585,5 @@ message ACLs {
repeated ACL.RemoveStandaloneContainer remove_standalone_container = 44;
repeated ACL.ViewStandaloneContainer view_standalone_containers = 46;
repeated ACL.ModifyResourceProviderConfig modify_resource_provider_configs = 45;
+ repeated ACL.PruneImages prune_images = 47;
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/4beb46db/include/mesos/authorizer/authorizer.proto
----------------------------------------------------------------------
diff --git a/include/mesos/authorizer/authorizer.proto b/include/mesos/authorizer/authorizer.proto
index 90ffdfa..1508c01 100644
--- a/include/mesos/authorizer/authorizer.proto
+++ b/include/mesos/authorizer/authorizer.proto
@@ -250,6 +250,10 @@ enum Action {
// allowed to add, update and remove resource provider config files or is
// unauthorized.
MODIFY_RESOURCE_PROVIDER_CONFIG = 39;
+
+ // This action will not fill in any object fields. A principal is either
+ // allowed to prune unused container images or is unauthorized.
+ PRUNE_IMAGES = 41;
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/4beb46db/src/authorizer/local/authorizer.cpp
----------------------------------------------------------------------
diff --git a/src/authorizer/local/authorizer.cpp b/src/authorizer/local/authorizer.cpp
index 0722ac9..b3ec601 100644
--- a/src/authorizer/local/authorizer.cpp
+++ b/src/authorizer/local/authorizer.cpp
@@ -412,6 +412,7 @@ public:
case authorization::STOP_MAINTENANCE:
case authorization::UPDATE_MAINTENANCE_SCHEDULE:
case authorization::MODIFY_RESOURCE_PROVIDER_CONFIG:
+ case authorization::PRUNE_IMAGES:
aclObject.set_type(ACL::Entity::ANY);
break;
@@ -700,6 +701,7 @@ public:
case authorization::LAUNCH_NESTED_CONTAINER_SESSION:
case authorization::LAUNCH_STANDALONE_CONTAINER:
case authorization::MARK_AGENT_GONE:
+ case authorization::PRUNE_IMAGES:
case authorization::REGISTER_AGENT:
case authorization::REMOVE_NESTED_CONTAINER:
case authorization::REMOVE_STANDALONE_CONTAINER:
@@ -917,6 +919,7 @@ public:
case authorization::LAUNCH_NESTED_CONTAINER_SESSION:
case authorization::LAUNCH_STANDALONE_CONTAINER:
case authorization::MARK_AGENT_GONE:
+ case authorization::PRUNE_IMAGES:
case authorization::REGISTER_AGENT:
case authorization::REMOVE_NESTED_CONTAINER:
case authorization::REMOVE_STANDALONE_CONTAINER:
@@ -1130,6 +1133,7 @@ public:
case authorization::KILL_STANDALONE_CONTAINER:
case authorization::LAUNCH_STANDALONE_CONTAINER:
case authorization::MARK_AGENT_GONE:
+ case authorization::PRUNE_IMAGES:
case authorization::REGISTER_AGENT:
case authorization::REMOVE_NESTED_CONTAINER:
case authorization::REMOVE_STANDALONE_CONTAINER:
@@ -1504,6 +1508,16 @@ private:
}
return acls_;
+ case authorization::PRUNE_IMAGES:
+ foreach (const ACL::PruneImages& acl, acls.prune_images()) {
+ GenericACL acl_;
+ acl_.subjects = acl.principals();
+ acl_.objects = acl.images();
+
+ acls_.push_back(acl_);
+ }
+
+ return acls_;
case authorization::REGISTER_FRAMEWORK:
case authorization::CREATE_VOLUME:
case authorization::RESERVE_RESOURCES:
@@ -1684,6 +1698,12 @@ Option<Error> LocalAuthorizer::validate(const ACLs& acls)
}
}
+ foreach (const ACL::PruneImages& acl, acls.prune_images()) {
+ if (acl.images().type() == ACL::Entity::SOME) {
+ return Error("acls.prune_images type must be either NONE or ANY");
+ }
+ }
+
// TODO(alexr): Consider validating not only protobuf, but also the original
// JSON in order to spot misspelled names. A misspelled action may affect
// authorization result and hence lead to a security issue (e.g. when there
http://git-wip-us.apache.org/repos/asf/mesos/blob/4beb46db/src/slave/http.cpp
----------------------------------------------------------------------
diff --git a/src/slave/http.cpp b/src/slave/http.cpp
index 446be55..71e0bbb 100644
--- a/src/slave/http.cpp
+++ b/src/slave/http.cpp
@@ -2444,8 +2444,6 @@ Future<Response> Http::pruneImages(
{
CHECK_EQ(agent::Call::PRUNE_IMAGES, call.type());
- // TODO(zhitao): Add AuthN/AuthZ.
-
LOG(INFO) << "Processing PRUNE_IMAGES call";
vector<Image> excludedImages(call.prune_images().excluded_images().begin(),
call.prune_images().excluded_images().end());
@@ -2458,25 +2456,47 @@ Future<Response> Http::pruneImages(
std::back_inserter(excludedImages));
}
- return slave->containerizer->pruneImages(excludedImages)
- .then([acceptType](const Future<Nothing>& result)
- ->Future<Response> {
- if (!result.isReady()) {
- // TODO(zhitao): Because `containerizer::pruneImages` returns
- // a `Nothing` now, we cannot distinguish between actual
- // failure or the case that operator should drain the agent.
- // Consider returning more information.
- LOG(WARNING)
- << "Failed to prune images: "
- << (result.isFailed() ? result.failure() : "discarded");
-
- return result.isFailed()
- ? InternalServerError(result.failure())
- : InternalServerError();
- }
+ Future<Owned<ObjectApprover>> approver;
- return OK();
- });
+ if (slave->authorizer.isSome()) {
+ Option<authorization::Subject> subject = createSubject(principal);
+
+ approver = slave->authorizer.get()->getObjectApprover(
+ subject,
+ authorization::PRUNE_IMAGES);
+ } else {
+ approver = Owned<ObjectApprover>(new AcceptingObjectApprover());
+ }
+
+ return approver
+ .then(defer(slave->self(), [this, excludedImages](
+ 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 slave->containerizer->pruneImages(excludedImages)
+ .then([](const Future<Nothing>& result) -> Future<Response> {
+ if (!result.isReady()) {
+ // TODO(zhitao): Because `containerizer::pruneImages` returns
+ // a `Nothing` now, we cannot distinguish between actual
+ // failure or the case that operator should drain the agent.
+ // Consider returning more information.
+ LOG(WARNING)
+ << "Failed to prune images: "
+ << (result.isFailed() ? result.failure() : "discarded");
+
+ return result.isFailed()
+ ? InternalServerError(result.failure())
+ : InternalServerError();
+ }
+
+ return OK();
+ });
+ }));
}