Repository: mesos Updated Branches: refs/heads/master 0dd86d182 -> b60b14487
Removed deprecated ACLs `SetQuota` and `RemoveQuota`. The ACLs `SetQuota` and `RemoveQuota` were marked for deprecation more than six months ago, where they were replaced with the more convenient `UpdateQuota` ACL. The deprecation cycle for these actions is finally due while at the same time removing will make it easier to implement the hierarchical role feature in a generic way. Review: https://reviews.apache.org/r/57472/ Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/b60b1448 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/b60b1448 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/b60b1448 Branch: refs/heads/master Commit: b60b1448734d0c6485bfa4ab18e6249ae99f8647 Parents: 0dd86d1 Author: Alexander Rojas <[email protected]> Authored: Thu Mar 30 01:00:06 2017 -0700 Committer: Adam B <[email protected]> Committed: Thu Mar 30 01:00:06 2017 -0700 ---------------------------------------------------------------------- CHANGELOG | 7 + docs/upgrades.md | 23 +++ include/mesos/authorizer/acls.proto | 35 +---- src/authorizer/local/authorizer.cpp | 96 +----------- src/master/master.hpp | 10 +- src/master/quota_handler.cpp | 40 +---- src/tests/authorization_tests.cpp | 246 ----------------------------- src/tests/master_quota_tests.cpp | 257 ------------------------------- 8 files changed, 48 insertions(+), 666 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/b60b1448/CHANGELOG ---------------------------------------------------------------------- diff --git a/CHANGELOG b/CHANGELOG index 875ae02..289069b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Release Notes - Mesos - Version 1.3.0 (WIP) ------------------------------------------- This release contains the following new features: + * [MESOS-1763] - Support for frameworks to receive resources for multiple roles. This allows "multi-user" frameworks to leverage the role-based resource allocation in mesos. Prior to this support, one had to run @@ -15,6 +16,12 @@ This release contains the following new features: (e.g. new employees join, new teams are formed, employees leave, teams are disbanded, etc). +Deprecations: + * [MESOS-7259] - Remove deprecated ACLs `SetQuota` and `RemoveQuota` + This change is only applicable to the local authorizer since internally + these acls were being translated to the `UPDATE_QUOTA` action. + + Release Notes - Mesos - Version 1.2.1 (WIP) ------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/b60b1448/docs/upgrades.md ---------------------------------------------------------------------- diff --git a/docs/upgrades.md b/docs/upgrades.md index c1e6524..249e844 100644 --- a/docs/upgrades.md +++ b/docs/upgrades.md @@ -43,6 +43,24 @@ We categorize the changes as follows: </thead> <tr> <td style="word-wrap: break-word; overflow-wrap: break-word;"><!--Version--> + 1.3.x + </td> + <td style="word-wrap: break-word; overflow-wrap: break-word;"><!--Mesos Core--> + </td> + <td style="word-wrap: break-word; overflow-wrap: break-word;"><!--Flags--> + <ul style="padding-left:10px;"> + <li>R <a href="1-3-x-setquota-removequota-acl">--acls (set_quotas and remove_quotas)</a></li> + </ul> + </td> + <td style="word-wrap: break-word; overflow-wrap: break-word;"><!--Framework API--> + </td> + <td style="word-wrap: break-word; overflow-wrap: break-word;"><!--Module API--> + </td> + <td style="word-wrap: break-word; overflow-wrap: break-word;"><!--Endpoints--> + </td> +</tr> +<tr> + <td style="word-wrap: break-word; overflow-wrap: break-word;"><!--Version--> 1.2.x </td> <td style="word-wrap: break-word; overflow-wrap: break-word;"><!--Mesos Core--> @@ -238,6 +256,11 @@ We categorize the changes as follows: </tr> </table> +## Upgrading from 1.2.x to 1.3.x ## + +<a name="1-3-x-setquota-removequota-acl"></a> +* Support for deprecated ACLs `set_quotas` and `remove_quotas` has been removed from the local authorizer. Before upgrading the Mesos binaries, consolidate the ACLs used under `set_quotas` and `remove_quotes` under their replacemente ACL `update_quotas`. After consolidation of the ACLs, the binaries could be safely replaced. + ## Upgrading from 1.1.x to 1.2.x ## <a name="1-2-x-heartbeat-flag"></a> http://git-wip-us.apache.org/repos/asf/mesos/blob/b60b1448/include/mesos/authorizer/acls.proto ---------------------------------------------------------------------- diff --git a/include/mesos/authorizer/acls.proto b/include/mesos/authorizer/acls.proto index 46e66e8..ae10027 100644 --- a/include/mesos/authorizer/acls.proto +++ b/include/mesos/authorizer/acls.proto @@ -142,30 +142,6 @@ message ACL { required Entity roles = 2; } - // Which principals are authorized to set quotas for given roles. - // - // TODO(zhitao): Remove this message at the end of the deprecation cycle - // which started with 1.0. It will be fully replaced by `UpdateQuota`. - message SetQuota { - // Subjects: Operator username. - required Entity principals = 1; - - // Objects: The list of roles for which a quota can be set. - required Entity roles = 2; - } - - // Which principals can remove quotas set by which other principals. - // - // TODO(zhitao): Remove this message at the end of the deprecation cycle - // which started with 1.0. It will be fully replaced by `UpdateQuota`. - message RemoveQuota { - // Subjects: Operator username. - required Entity principals = 1; - - // Objects: Principal of the entity that set the quota. - required Entity quota_principals = 2; - } - // Which principals are authorized to view information (including weights) // about the given roles. message ViewRole { @@ -403,6 +379,11 @@ message ACL { * * NOTE: Fields in this message should be kept in * numerical order to avoid accidental tag reuse. + * + * NOTE: Do not use '9' and '10' as field identifiers, since they were + * used by removed entries and can cause conflict with old versions of + * the file. + * */ message ACLs { optional bool permissive = 1 [default = true]; @@ -415,12 +396,6 @@ message ACLs { repeated ACL.UnreserveResources unreserve_resources = 6; repeated ACL.CreateVolume create_volumes = 7; repeated ACL.DestroyVolume destroy_volumes = 8; - - // TODO(zhitao): Remove the following two fields at the end - // of the deprecation cycle which started with 1.0. - repeated ACL.SetQuota set_quotas = 9 [deprecated = true]; - repeated ACL.RemoveQuota remove_quotas = 10 [deprecated = true]; - repeated ACL.TeardownFramework teardown_frameworks = 11; repeated ACL.UpdateWeight update_weights = 12; repeated ACL.GetEndpoint get_endpoints = 13; http://git-wip-us.apache.org/repos/asf/mesos/blob/b60b1448/src/authorizer/local/authorizer.cpp ---------------------------------------------------------------------- diff --git a/src/authorizer/local/authorizer.cpp b/src/authorizer/local/authorizer.cpp index be80372..e241edf 100644 --- a/src/authorizer/local/authorizer.cpp +++ b/src/authorizer/local/authorizer.cpp @@ -59,28 +59,6 @@ struct GenericACL }; -// TODO(mpark): This class exists to optionally carry `ACL::SetQuota` and -// `ACL::RemoveQuota` ACLs. This is a hack to support the deprecation cycle for -// `ACL::SetQuota` and `ACL::RemoveQuota`. This can be removed / replaced with -// `vector<GenericACL>` at the end of deprecation cycle which started with 1.0. -struct GenericACLs -{ - GenericACLs(const vector<GenericACL>& acls_) : acls(acls_) {} - - GenericACLs( - const vector<GenericACL>& acls_, - const vector<GenericACL>& set_quotas_, - const vector<GenericACL>& remove_quotas_) - : acls(acls_), set_quotas(set_quotas_), remove_quotas(remove_quotas_) {} - - vector<GenericACL> acls; - - // These ACLs are set iff the authorization action is `UPDATE_QUOTA`. - Option<vector<GenericACL>> set_quotas; - Option<vector<GenericACL>> remove_quotas; -}; - - // Match matrix: // // -----------ACL---------- @@ -193,7 +171,7 @@ class LocalAuthorizerObjectApprover : public ObjectApprover { public: LocalAuthorizerObjectApprover( - const GenericACLs& acls, + const vector<GenericACL>& acls, const Option<authorization::Subject>& subject, const authorization::Action& action, bool permissive) @@ -377,30 +355,6 @@ public: // Check object has the required types set. CHECK_NOTNULL(object->quota_info); - // TODO(mpark): This is a hack to support the deprecation cycle for - // `ACL::SetQuota` and `ACL::RemoveQuota`. This block of code can be - // removed at the end of deprecation cycle which started with 1.0. - if (acls_.set_quotas->size() > 0 || acls_.remove_quotas->size() > 0) { - CHECK_NOTNULL(object->value); - if (*object->value == "SetQuota") { - aclObject.add_values(object->quota_info->role()); - aclObject.set_type(mesos::ACL::Entity::SOME); - - CHECK_SOME(acls_.set_quotas); - return approved(acls_.set_quotas.get(), aclSubject, aclObject); - } else if (*object->value == "RemoveQuota") { - if (object->quota_info->has_principal()) { - aclObject.add_values(object->quota_info->principal()); - aclObject.set_type(mesos::ACL::Entity::SOME); - } else { - aclObject.set_type(mesos::ACL::Entity::ANY); - } - - CHECK_SOME(acls_.remove_quotas); - return approved(acls_.remove_quotas.get(), aclSubject, aclObject); - } - } - aclObject.add_values(object->quota_info->role()); aclObject.set_type(mesos::ACL::Entity::SOME); @@ -506,7 +460,7 @@ public: } } - return approved(acls_.acls, aclSubject, aclObject); + return approved(acls_, aclSubject, aclObject); } private: @@ -525,7 +479,7 @@ private: return permissive_; // None of the ACLs match. } - const GenericACLs acls_; + const vector<GenericACL> acls_; const Option<authorization::Subject> subject_; const authorization::Action action_; const bool permissive_; @@ -536,8 +490,8 @@ class LocalNestedContainerObjectApprover : public ObjectApprover { public: LocalNestedContainerObjectApprover( - const GenericACLs& userAcls, - const GenericACLs& parentAcls, + const vector<GenericACL>& userAcls, + const vector<GenericACL>& parentAcls, const Option<authorization::Subject>& subject, const authorization::Action& action, bool permissive) @@ -592,14 +546,6 @@ public: virtual void initialize() { - // TODO(zhitao): Remove the following log warning at the end of the - // deprecation cycle which started with 1.0. - if (acls.set_quotas_size() > 0 || - acls.remove_quotas_size() > 0) { - LOG(WARNING) << "SetQuota and RemoveQuota ACLs are deprecated; " - << "please use UpdateQuota"; - } - // TODO(arojas): Remove the following two if blocks once // ShutdownFramework reaches the end of deprecation cycle // which started with 0.27.0. @@ -719,8 +665,7 @@ public: return getNestedContainerObjectApprover(subject, action); } - // Generate GenericACLs. - Result<GenericACLs> genericACLs = createGenericACLs(action, acls); + Result<vector<GenericACL>> genericACLs = createGenericACLs(action, acls); if (genericACLs.isError()) { return Failure(genericACLs.error()); } @@ -736,7 +681,7 @@ public: } private: - static Result<GenericACLs> createGenericACLs( + static Result<vector<GenericACL>> createGenericACLs( const authorization::Action& action, const ACLs& acls) { @@ -843,25 +788,7 @@ private: acls_.push_back(acl_); } - vector<GenericACL> set_quotas; - foreach (const ACL::SetQuota& acl, acls.set_quotas()) { - GenericACL acl_; - acl_.subjects = acl.principals(); - acl_.objects = acl.roles(); - - set_quotas.push_back(acl_); - } - - vector<GenericACL> remove_quotas; - foreach (const ACL::RemoveQuota& acl, acls.remove_quotas()) { - GenericACL acl_; - acl_.subjects = acl.principals(); - acl_.objects = acl.quota_principals(); - - remove_quotas.push_back(acl_); - } - - return GenericACLs(acls_, set_quotas, remove_quotas); + return acls_; break; } case authorization::VIEW_ROLE: @@ -1100,13 +1027,6 @@ Try<Authorizer*> LocalAuthorizer::create(const Parameters& parameters) Option<Error> LocalAuthorizer::validate(const ACLs& acls) { - if (acls.update_quotas_size() > 0 && - (acls.set_quotas_size() > 0 || acls.remove_quotas_size() > 0)) { - return Error("acls.update_quotas cannot be used " - "together with deprecated set_quotas/remove_quotas!"); - } - - foreach (const ACL::AccessMesosLog& acl, acls.access_mesos_logs()) { if (acl.logs().type() == ACL::Entity::SOME) { return Error("acls.access_mesos_logs type must be either NONE or ANY"); http://git-wip-us.apache.org/repos/asf/mesos/blob/b60b1448/src/master/master.hpp ---------------------------------------------------------------------- diff --git a/src/master/master.hpp b/src/master/master.hpp index d92c8ad..98364d7 100644 --- a/src/master/master.hpp +++ b/src/master/master.hpp @@ -1057,15 +1057,7 @@ private: const Option<process::http::authentication::Principal>& principal, const mesos::quota::QuotaInfo& quotaInfo) const; - // TODO(mpark): The following functions `authorizeSetQuota` and - // `authorizeRemoveQuota` should be replaced with `authorizeUpdateQuota` at - // the end of deprecation cycle which started with 1.0. - - process::Future<bool> authorizeSetQuota( - const Option<process::http::authentication::Principal>& principal, - const mesos::quota::QuotaInfo& quotaInfo) const; - - process::Future<bool> authorizeRemoveQuota( + process::Future<bool> authorizeUpdateQuota( const Option<process::http::authentication::Principal>& principal, const mesos::quota::QuotaInfo& quotaInfo) const; http://git-wip-us.apache.org/repos/asf/mesos/blob/b60b1448/src/master/quota_handler.cpp ---------------------------------------------------------------------- diff --git a/src/master/quota_handler.cpp b/src/master/quota_handler.cpp index 36ea1ac..7ff43a0 100644 --- a/src/master/quota_handler.cpp +++ b/src/master/quota_handler.cpp @@ -388,7 +388,7 @@ Future<http::Response> Master::QuotaHandler::_set( quotaInfo.set_principal(principal->value.get()); } - return authorizeSetQuota(principal, quotaInfo) + return authorizeUpdateQuota(principal, quotaInfo) .then(defer(master->self(), [=](bool authorized) -> Future<http::Response> { return !authorized ? Forbidden() : __set(quotaInfo, forced); })); @@ -508,7 +508,7 @@ Future<http::Response> Master::QuotaHandler::_remove( const string& role, const Option<Principal>& principal) const { - return authorizeRemoveQuota(principal, master->quotas.at(role).info) + return authorizeUpdateQuota(principal, master->quotas.at(role).info) .then(defer(master->self(), [=](bool authorized) -> Future<http::Response> { return !authorized ? Forbidden() : __remove(role); })); @@ -568,9 +568,7 @@ Future<bool> Master::QuotaHandler::authorizeGetQuota( } -// TODO(zhitao): Remove this function at the end of the -// deprecation cycle which started with 1.0. -Future<bool> Master::QuotaHandler::authorizeSetQuota( +Future<bool> Master::QuotaHandler::authorizeUpdateQuota( const Option<Principal>& principal, const QuotaInfo& quotaInfo) const { @@ -580,7 +578,7 @@ Future<bool> Master::QuotaHandler::authorizeSetQuota( LOG(INFO) << "Authorizing principal '" << (principal.isSome() ? stringify(principal.get()) : "ANY") - << "' to set quota for role '" << quotaInfo.role() << "'"; + << "' to update quota for role '" << quotaInfo.role() << "'"; authorization::Request request; request.set_action(authorization::UPDATE_QUOTA); @@ -590,36 +588,6 @@ Future<bool> Master::QuotaHandler::authorizeSetQuota( request.mutable_subject()->CopyFrom(subject.get()); } - request.mutable_object()->set_value("SetQuota"); - request.mutable_object()->mutable_quota_info()->CopyFrom(quotaInfo); - - return master->authorizer.get()->authorized(request); -} - - -// TODO(zhitao): Remove this function at the end of the -// deprecation cycle which started with 1.0. -Future<bool> Master::QuotaHandler::authorizeRemoveQuota( - const Option<Principal>& principal, - const QuotaInfo& quotaInfo) const -{ - if (master->authorizer.isNone()) { - return true; - } - - LOG(INFO) << "Authorizing principal '" - << (principal.isSome() ? stringify(principal.get()) : "ANY") - << "' to remove quota for role '" << quotaInfo.role() << "'"; - - authorization::Request request; - request.set_action(authorization::UPDATE_QUOTA); - - Option<authorization::Subject> subject = createSubject(principal); - if (subject.isSome()) { - request.mutable_subject()->CopyFrom(subject.get()); - } - - request.mutable_object()->set_value("RemoveQuota"); request.mutable_object()->mutable_quota_info()->CopyFrom(quotaInfo); return master->authorizer.get()->authorized(request); http://git-wip-us.apache.org/repos/asf/mesos/blob/b60b1448/src/tests/authorization_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/authorization_tests.cpp b/src/tests/authorization_tests.cpp index 9f63682..3e18c70 100644 --- a/src/tests/authorization_tests.cpp +++ b/src/tests/authorization_tests.cpp @@ -1574,252 +1574,6 @@ TYPED_TEST(AuthorizationTest, UpdateQuota) } -// This tests that update_quotas and set_quotas/remove_quotas -// cannot be used together. -// TODO(zhitao): Remove this test case at the end of the deprecation -// cycle started with 1.0. -TYPED_TEST(AuthorizationTest, ConflictQuotaACLs) { - { - ACLs acls; - - { - // Add an UpdateQuota ACL. - mesos::ACL::UpdateQuota* acl = acls.add_update_quotas(); - acl->mutable_principals()->add_values("foo"); - acl->mutable_roles()->set_type(mesos::ACL::Entity::ANY); - } - - { - // Add a SetQuota ACL. - mesos::ACL::SetQuota* acl = acls.add_set_quotas(); - acl->mutable_principals()->add_values("foo"); - acl->mutable_roles()->set_type(mesos::ACL::Entity::ANY); - } - - // Create an `Authorizer` with the ACLs should error out. - Try<Authorizer*> create = TypeParam::create(parameterize(acls)); - ASSERT_ERROR(create); - } - - { - ACLs acls; - - { - // Add an UpdateQuota ACL. - mesos::ACL::UpdateQuota* acl = acls.add_update_quotas(); - acl->mutable_principals()->add_values("foo"); - acl->mutable_roles()->set_type(mesos::ACL::Entity::ANY); - } - - { - // Add a RemoveQuota ACL. - mesos::ACL::RemoveQuota* acl = acls.add_remove_quotas(); - acl->mutable_principals()->add_values("foo"); - acl->mutable_quota_principals()->set_type(mesos::ACL::Entity::ANY); - } - - // Create an `Authorizer` with the ACLs should error out. - Try<Authorizer*> create = TypeParam::create(parameterize(acls)); - ASSERT_ERROR(create); - } -} - - -// This tests the authorization of requests to set quotas. -// TODO(zhitao): Remove this test case at the end of the deprecation -// cycle started with 1.0. -TYPED_TEST(AuthorizationTest, SetQuota) -{ - ACLs acls; - - { - // "foo" principal can set quotas for all roles. - mesos::ACL::SetQuota* acl = acls.add_set_quotas(); - acl->mutable_principals()->add_values("foo"); - acl->mutable_roles()->set_type(mesos::ACL::Entity::ANY); - } - - { - // "bar" principal can set quotas for "dev" role. - mesos::ACL::SetQuota* acl = acls.add_set_quotas(); - acl->mutable_principals()->add_values("bar"); - acl->mutable_roles()->add_values("dev"); - } - { - // Anyone can set quotas for "test" role. - mesos::ACL::SetQuota* acl = acls.add_set_quotas(); - acl->mutable_principals()->set_type(mesos::ACL::Entity::ANY); - acl->mutable_roles()->add_values("test"); - } - - { - // No other principal can set quotas. - mesos::ACL::SetQuota* acl = acls.add_set_quotas(); - acl->mutable_principals()->set_type(mesos::ACL::Entity::ANY); - acl->mutable_roles()->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()); - - // Principal "foo" can set quota for all roles, so this will pass. - { - authorization::Request request; - request.set_action(authorization::UPDATE_QUOTA); - request.mutable_subject()->set_value("foo"); - request.mutable_object()->set_value("SetQuota"); - request.mutable_object()->mutable_quota_info()->set_role("prod"); - AWAIT_EXPECT_TRUE(authorizer.get()->authorized(request)); - } - - // Principal "bar" can set quotas for role "dev", so this will pass. - { - authorization::Request request; - request.set_action(authorization::UPDATE_QUOTA); - request.mutable_subject()->set_value("bar"); - request.mutable_object()->set_value("SetQuota"); - request.mutable_object()->mutable_quota_info()->set_role("dev"); - AWAIT_EXPECT_TRUE(authorizer.get()->authorized(request)); - } - - // Principal "bar" can only set quotas for role "dev", so this will fail. - { - authorization::Request request; - request.set_action(authorization::UPDATE_QUOTA); - request.mutable_subject()->set_value("bar"); - request.mutable_object()->set_value("SetQuota"); - request.mutable_object()->mutable_quota_info()->set_role("prod"); - AWAIT_EXPECT_FALSE(authorizer.get()->authorized(request)); - } - - // Anyone can set quotas for role "test", so request 6 will pass. - { - authorization::Request request; - request.set_action(authorization::UPDATE_QUOTA); - request.mutable_object()->set_value("SetQuota"); - request.mutable_object()->mutable_quota_info()->set_role("test"); - AWAIT_EXPECT_TRUE(authorizer.get()->authorized(request)); - } - - // Principal "jeff" is not mentioned in the ACLs of the `Authorizer`, so it - // will be caught by the final ACL, which provides a default case that denies - // access for all other principals. This case will fail. - { - authorization::Request request; - request.set_action(authorization::UPDATE_QUOTA); - request.mutable_subject()->set_value("jeff"); - request.mutable_object()->set_value("SetQuota"); - request.mutable_object()->mutable_quota_info()->set_role("prod"); - AWAIT_EXPECT_FALSE(authorizer.get()->authorized(request)); - } -} - - -// This tests the authorization of requests to remove quotas. -// TODO(zhitao): Remove this test case at the end of the deprecation -// cycle started with 1.0. -TYPED_TEST(AuthorizationTest, RemoveQuota) -{ - ACLs acls; - - { - // "foo" principal can remove its own quotas. - mesos::ACL::RemoveQuota* acl = acls.add_remove_quotas(); - acl->mutable_principals()->add_values("foo"); - acl->mutable_quota_principals()->add_values("foo"); - } - - { - // "bar" principal cannot remove anyone's quotas. - mesos::ACL::RemoveQuota* acl = acls.add_remove_quotas(); - acl->mutable_principals()->add_values("bar"); - acl->mutable_quota_principals()->set_type(mesos::ACL::Entity::NONE); - } - - { - // "ops" principal can remove anyone's quotas. - mesos::ACL::RemoveQuota* acl = acls.add_remove_quotas(); - acl->mutable_principals()->add_values("ops"); - acl->mutable_quota_principals()->set_type(mesos::ACL::Entity::ANY); - } - - { - // No other principals can remove quotas. - mesos::ACL::RemoveQuota* acl = acls.add_remove_quotas(); - acl->mutable_principals()->set_type(mesos::ACL::Entity::ANY); - acl->mutable_quota_principals()->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()); - - // Principal "foo" can remove its own quotas, so request 1 will pass. - { - authorization::Request request; - request.set_action(authorization::UPDATE_QUOTA); - request.mutable_subject()->set_value("foo"); - request.mutable_object()->set_value("RemoveQuota"); - request.mutable_object()->mutable_quota_info()->set_principal("foo"); - AWAIT_EXPECT_TRUE(authorizer.get()->authorized(request)); - } - - // Principal "bar" cannot remove anyone's quotas, so requests 2 and 3 will - // fail. - { - authorization::Request request; - request.set_action(authorization::UPDATE_QUOTA); - request.mutable_subject()->set_value("bar"); - request.mutable_object()->set_value("RemoveQuota"); - request.mutable_object()->mutable_quota_info()->set_principal("bar"); - AWAIT_EXPECT_FALSE(authorizer.get()->authorized(request)); - } - - { - authorization::Request request; - request.set_action(authorization::UPDATE_QUOTA); - request.mutable_subject()->set_value("bar"); - request.mutable_object()->set_value("RemoveQuota"); - request.mutable_object()->mutable_quota_info()->set_principal("foo"); - AWAIT_EXPECT_FALSE(authorizer.get()->authorized(request)); - } - - // Principal "ops" can remove anyone's quotas, so requests 4 and 5 will pass. - { - authorization::Request request; - request.set_action(authorization::UPDATE_QUOTA); - request.mutable_subject()->set_value("ops"); - request.mutable_object()->set_value("RemoveQuota"); - request.mutable_object()->mutable_quota_info()->set_principal("foo"); - AWAIT_EXPECT_TRUE(authorizer.get()->authorized(request)); - } - - { - authorization::Request request; - request.set_action(authorization::UPDATE_QUOTA); - request.mutable_subject()->set_value("ops"); - request.mutable_object()->set_value("RemoveQuota"); - request.mutable_object()->mutable_quota_info(); - AWAIT_EXPECT_TRUE(authorizer.get()->authorized(request)); - } - - // Principal "jeff" is not mentioned in the ACLs of the `Authorizer`, so it - // will be caught by the final rule, which provides a default case that denies - // access for all other principals. This case will fail. - { - authorization::Request request; - request.set_action(authorization::UPDATE_QUOTA); - request.mutable_subject()->set_value("jeff"); - request.mutable_object()->set_value("RemoveQuota"); - request.mutable_object()->mutable_quota_info()->set_principal("foo"); - AWAIT_EXPECT_FALSE(authorizer.get()->authorized(request)); - } -} - - // This tests the authorization of requests to ViewFramework. TYPED_TEST(AuthorizationTest, ViewFramework) { http://git-wip-us.apache.org/repos/asf/mesos/blob/b60b1448/src/tests/master_quota_tests.cpp ---------------------------------------------------------------------- diff --git a/src/tests/master_quota_tests.cpp b/src/tests/master_quota_tests.cpp index e418f22..1714ba1 100644 --- a/src/tests/master_quota_tests.cpp +++ b/src/tests/master_quota_tests.cpp @@ -1384,197 +1384,6 @@ TEST_F(MasterQuotaTest, AuthorizeGetUpdateQuotaRequests) } -// Checks that an authorized principal can update quota using deprecated -// set_quotas and remove_quotas, while unauthorized principals cannot. -// -// TODO(zhitao): Remove this test case at the end of deprecation cycle -// started with 1.0. -TEST_F(MasterQuotaTest, AuthorizeSetAndRemoveQuotaRequests) -{ - TestAllocator<> allocator; - EXPECT_CALL(allocator, initialize(_, _, _, _)); - - // Setup ACLs so that only the default principal can set and see - // quotas for `ROLE1` and can remove its own quotas. - ACLs acls; - - mesos::ACL::SetQuota* acl1 = acls.add_set_quotas(); - acl1->mutable_principals()->add_values(DEFAULT_CREDENTIAL.principal()); - acl1->mutable_roles()->add_values(ROLE1); - - mesos::ACL::SetQuota* acl2 = acls.add_set_quotas(); - acl2->mutable_principals()->set_type(mesos::ACL::Entity::ANY); - acl2->mutable_roles()->set_type(mesos::ACL::Entity::NONE); - - mesos::ACL::RemoveQuota* acl3 = acls.add_remove_quotas(); - acl3->mutable_principals()->add_values(DEFAULT_CREDENTIAL.principal()); - acl3->mutable_quota_principals()->add_values(DEFAULT_CREDENTIAL.principal()); - - mesos::ACL::RemoveQuota* acl4 = acls.add_remove_quotas(); - acl4->mutable_principals()->set_type(mesos::ACL::Entity::ANY); - acl4->mutable_quota_principals()->set_type(mesos::ACL::Entity::NONE); - - mesos::ACL::GetQuota* acl5 = acls.add_get_quotas(); - acl5->mutable_principals()->add_values(DEFAULT_CREDENTIAL.principal()); - acl5->mutable_roles()->add_values(ROLE1); - - mesos::ACL::GetQuota* acl6 = acls.add_get_quotas(); - acl6->mutable_principals()->set_type(mesos::ACL::Entity::ANY); - acl6->mutable_roles()->set_type(mesos::ACL::Entity::NONE); - - master::Flags masterFlags = CreateMasterFlags(); - masterFlags.acls = acls; - - Try<Owned<cluster::Master>> master = StartMaster(&allocator, masterFlags); - ASSERT_SOME(master); - - // Use the force flag for setting quota that cannot be satisfied in - // this empty cluster without any agents. - const bool FORCE = true; - - // Try to request quota using a principal that is not the default principal. - // This request will fail because only the default principal is authorized - // to do that. - { - // As we don't care about the enforcement of quota but only the - // authorization of the quota request we set the force flag in the post - // request below to override the capacity heuristic check. - Resources quotaResources = Resources::parse("cpus:1;mem:512").get(); - - Future<Response> response = process::http::post( - master.get()->pid, - "quota", - createBasicAuthHeaders(DEFAULT_CREDENTIAL_2), - createRequestBody(ROLE1, quotaResources, FORCE)); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(Forbidden().status, response) - << response->body; - } - - // Request quota using the default principal. - { - // As we don't care about the enforcement of quota but only the - // authorization of the quota request we set the force flag in the post - // request below to override the capacity heuristic check. - Resources quotaResources = Resources::parse("cpus:1;mem:512").get(); - - Future<Quota> quota; - EXPECT_CALL(allocator, setQuota(Eq(ROLE1), _)) - .WillOnce(DoAll(InvokeSetQuota(&allocator), - FutureArg<1>("a))); - - Future<Response> response = process::http::post( - master.get()->pid, - "quota", - createBasicAuthHeaders(DEFAULT_CREDENTIAL), - createRequestBody(ROLE1, quotaResources, FORCE)); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response) - << response->body; - - AWAIT_READY(quota); - - // Extract the principal from `DEFAULT_CREDENTIAL` because `EXPECT_EQ` - // does not compile if `DEFAULT_CREDENTIAL.principal()` is used as an - // argument. - const string principal = DEFAULT_CREDENTIAL.principal(); - - EXPECT_EQ(ROLE1, quota->info.role()); - EXPECT_EQ(principal, quota->info.principal()); - EXPECT_EQ(quotaResources, quota->info.guarantee()); - } - - // Try to get the previously requested quota using a principal that is - // not authorized to see it. This will result in empty information - // returned. - { - Future<Response> response = process::http::get( - master.get()->pid, - "quota", - None(), - createBasicAuthHeaders(DEFAULT_CREDENTIAL_2)); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response) - << response->body; - - EXPECT_SOME_EQ( - "application/json", - response->headers.get("Content-Type")); - - const Try<JSON::Object> parse = - JSON::parse<JSON::Object>(response->body); - - ASSERT_SOME(parse); - - // Convert JSON response to `QuotaStatus` protobuf. - const Try<QuotaStatus> status = ::protobuf::parse<QuotaStatus>(parse.get()); - ASSERT_FALSE(status.isError()); - - EXPECT_EQ(0, status->infos().size()); - } - - // Get the previously requested quota using the default principal, which is - // authorized to see it. - { - Future<Response> response = process::http::get( - master.get()->pid, - "quota", - None(), - createBasicAuthHeaders(DEFAULT_CREDENTIAL)); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response) - << response->body; - - EXPECT_SOME_EQ( - "application/json", - response->headers.get("Content-Type")); - - const Try<JSON::Object> parse = - JSON::parse<JSON::Object>(response->body); - - ASSERT_SOME(parse); - - // Convert JSON response to `QuotaStatus` protobuf. - const Try<QuotaStatus> status = ::protobuf::parse<QuotaStatus>(parse.get()); - ASSERT_FALSE(status.isError()); - - EXPECT_EQ(1, status->infos().size()); - EXPECT_EQ(ROLE1, status->infos(0).role()); - } - - // Try to remove the previously requested quota using a principal that is - // not the default principal. This will fail because only the default - // principal is authorized to do that. - { - Future<Response> response = process::http::requestDelete( - master.get()->pid, - "quota/" + ROLE1, - createBasicAuthHeaders(DEFAULT_CREDENTIAL_2)); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(Forbidden().status, response) - << response->body; - } - - // Remove the previously requested quota using the default principal. - { - Future<Nothing> receivedRemoveRequest; - EXPECT_CALL(allocator, removeQuota(Eq(ROLE1))) - .WillOnce(DoAll(InvokeRemoveQuota(&allocator), - FutureSatisfy(&receivedRemoveRequest))); - - Future<Response> response = process::http::requestDelete( - master.get()->pid, - "quota/" + ROLE1, - createBasicAuthHeaders(DEFAULT_CREDENTIAL)); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response) - << response->body; - - AWAIT_READY(receivedRemoveRequest); - } -} - - // Checks that get and update quota requests can be authorized without // authentication if an authorization rule exists that applies to anyone. // The authorizer will map the absence of a principal to "ANY". @@ -1666,72 +1475,6 @@ TEST_F(MasterQuotaTest, AuthorizeGetUpdateQuotaRequestsWithoutPrincipal) } } - -// Checks that set and remove quota requests can be authorized without -// authentication if an authorization rule exists that applies to anyone. -// The authorizer will map the absence of a principal to "ANY". -// -// TODO(zhitao): Remove this test case at the end of deprecation cycle -// started with 1.0. -TEST_F(MasterQuotaTest, AuthorizeSetRemoveQuotaRequestsWithoutPrincipal) -{ - // Setup ACLs so that any principal can set quotas for `ROLE1` and remove - // anyone's quotas. - ACLs acls; - - mesos::ACL::SetQuota* acl1 = acls.add_set_quotas(); - acl1->mutable_principals()->set_type(mesos::ACL::Entity::ANY); - acl1->mutable_roles()->add_values(ROLE1); - - mesos::ACL::RemoveQuota* acl2 = acls.add_remove_quotas(); - acl2->mutable_principals()->set_type(mesos::ACL::Entity::ANY); - acl2->mutable_quota_principals()->set_type(mesos::ACL::Entity::ANY); - - master::Flags masterFlags = CreateMasterFlags(); - masterFlags.acls = acls; - masterFlags.authenticate_http_readonly = false; - masterFlags.authenticate_http_readwrite = false; - masterFlags.authenticate_http_frameworks = false; - masterFlags.credentials = None(); - - Try<Owned<cluster::Master>> master = StartMaster(masterFlags); - ASSERT_SOME(master); - - // Use the force flag for setting quota that cannot be satisfied in - // this empty cluster without any agents. - const bool FORCE = true; - - // Request quota without providing authorization headers. - { - // As we don't care about the enforcement of quota but only the - // authorization of the quota request we set the force flag in the post - // request below to override the capacity heuristic check. - Resources quotaResources = Resources::parse("cpus:1;mem:512").get(); - - // Create an HTTP request without authorization headers. - Future<Response> response = process::http::post( - master.get()->pid, - "quota", - None(), - createRequestBody(ROLE1, quotaResources, FORCE)); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response) - << response->body; - } - - // Remove the previously requested quota without providing authorization - // headers. - { - Future<Response> response = process::http::requestDelete( - master.get()->pid, - "quota/" + ROLE1, - None()); - - AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response) - << response->body; - } -} - } // namespace tests { } // namespace internal { } // namespace mesos {
