diff --git a/swift/common/middleware/keystoneauth.py b/swift/common/middleware/keystoneauth.py index 5c09c85ad7..3630a1bb77 100644 --- a/swift/common/middleware/keystoneauth.py +++ b/swift/common/middleware/keystoneauth.py @@ -204,6 +204,14 @@ class KeystoneAuth(object): req.environ['swift_owner'] = True return + # If we are not reseller admin and user is trying to delete its own + # account then deny it. + if not container and not obj and req.method == 'DELETE': + # User is not allowed to issue a DELETE on its own account + msg = 'User %s:%s is not allowed to delete its own account' + self.logger.debug(msg % (tenant_name, user_name)) + return self.denied_response(req) + # cross-tenant authorization matched_acl = self._authorize_cross_tenant(user_id, user_name, tenant_id, tenant_name, diff --git a/test/unit/common/middleware/test_keystoneauth.py b/test/unit/common/middleware/test_keystoneauth.py index cd0d0c7e8c..6d13a0b89a 100644 --- a/test/unit/common/middleware/test_keystoneauth.py +++ b/test/unit/common/middleware/test_keystoneauth.py @@ -202,7 +202,11 @@ class TestAuthorize(unittest.TestCase): req = self._make_request(path, headers=headers, environ=default_env) req.acl = acl result = self.test_auth.authorize(req) - if exception: + + # if we have requested an exception but nothing came back then + if exception and not result: + self.fail("error %s was not returned" % (str(exception))) + elif exception: self.assertEquals(result.status_int, exception) else: self.assertTrue(result is None) @@ -335,6 +339,25 @@ class TestAuthorize(unittest.TestCase): self.assertEqual(self.test_auth._authorize_cross_tenant('userID', 'userA', 'tenantID', 'tenantNAME', ['tenantXYZ:userA']), None) + def test_delete_own_account_not_allowed(self): + roles = self.test_auth.operator_roles.split(',') + identity = self._get_identity(roles=roles) + account = self._get_account(identity) + self._check_authenticate(account=account, + identity=identity, + exception=HTTP_FORBIDDEN, + path='/v1/' + account, + env={'REQUEST_METHOD': 'DELETE'}) + + def test_delete_own_account_when_reseller_allowed(self): + roles = [self.test_auth.reseller_admin_role] + identity = self._get_identity(roles=roles) + account = self._get_account(identity) + req = self._check_authenticate(account=account, + identity=identity, + path='/v1/' + account, + env={'REQUEST_METHOD': 'DELETE'}) + self.assertEqual(bool(req.environ.get('swift_owner')), True) if __name__ == '__main__': unittest.main()