]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: user suspension
authorYehuda Sadeh <yehuda@hq.newdream.net>
Thu, 16 Jun 2011 23:53:38 +0000 (16:53 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Thu, 16 Jun 2011 23:53:38 +0000 (16:53 -0700)
src/include/rados/librados.h
src/include/rados/librados.hpp
src/librados.cc
src/rgw/rgw_access.h
src/rgw/rgw_admin.cc
src/rgw/rgw_common.h
src/rgw/rgw_main.cc
src/rgw/rgw_op.cc
src/rgw/rgw_rados.cc
src/rgw/rgw_rados.h
src/rgw/rgw_rest.cc

index efc661831c372a238edaa3024bad761b9590b758..ae735bb2e96da075ba979a24ce90801d04354e5f 100644 (file)
@@ -112,6 +112,7 @@ int rados_pool_create_with_all(rados_t cluster, const char *pool_name, uint64_t
                                     __u8 crush_rule);
 int rados_pool_delete(rados_t cluster, const char *pool_name);
 int rados_ioctx_pool_set_auid(rados_ioctx_t io, uint64_t auid);
+int rados_ioctx_pool_get_auid(rados_ioctx_t io, uint64_t *auid);
 
 void rados_ioctx_locator_set_key(rados_ioctx_t io, const char *key);
 int rados_ioctx_get_id(rados_ioctx_t io);
index 4bcf96b6b9a644e2a67b5beb96d58d2840b27cbe..fd7ec6468d7cf7ff1ab755714d31d27e322f3cb7 100644 (file)
@@ -150,6 +150,9 @@ namespace librados
     // set pool auid
     int set_auid(uint64_t auid_);
 
+    // get pool auid
+    int get_auid(uint64_t *auid_);
+
     // create an object
     int create(const std::string& oid, bool exclusive);
 
index 3c51689eb1497785cb85b54740f0bb09a9cb0789..85b9e91ef2afcba3665b6c186c23b4a132a348cd 100644 (file)
@@ -474,6 +474,7 @@ public:
   int pool_create(string& name, unsigned long long auid=0, __u8 crush_rule=0);
   int pool_delete(const char *name);
   int pool_change_auid(rados_ioctx_t io, unsigned long long auid);
+  int pool_get_auid(rados_ioctx_t io, unsigned long long *auid);
 
   int list(Objecter::ListContext *context, int max_entries);
 
@@ -1122,6 +1123,18 @@ pool_change_auid(rados_ioctx_t io, unsigned long long auid)
   return reply;
 }
 
+int librados::RadosClient::
+pool_get_auid(rados_ioctx_t io, unsigned long long *auid)
+{
+  Mutex::Locker l(lock);
+  int pool_id = ((IoCtxImpl *)io)->poolid;
+  const pg_pool_t *pg = osdmap.get_pg_pool(pool_id);
+  if (!pg)
+    return -ENOENT;
+  *auid = pg->v.auid;
+  return 0;
+}
+
 int librados::RadosClient::
 snap_list(IoCtxImpl *io, vector<uint64_t> *snaps)
 {
@@ -2395,6 +2408,12 @@ set_auid(uint64_t auid_)
   return io_ctx_impl->client->pool_change_auid(io_ctx_impl, auid_);
 }
 
+int librados::IoCtx::
+get_auid(uint64_t *auid_)
+{
+  return io_ctx_impl->client->pool_get_auid(io_ctx_impl, (unsigned long long *)auid_);
+}
+
 int librados::IoCtx::
 create(const std::string& oid, bool exclusive)
 {
@@ -3269,6 +3288,12 @@ extern "C" int rados_ioctx_pool_set_auid(rados_ioctx_t io, uint64_t auid)
   return ctx->client->pool_change_auid(ctx, auid);
 }
 
+extern "C" int rados_ioctx_pool_get_auid(rados_ioctx_t io, uint64_t *auid)
+{
+  librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
+  return ctx->client->pool_get_auid(ctx, (unsigned long long *)auid);
+}
+
 extern "C" void rados_ioctx_locator_set_key(rados_ioctx_t io, const char *key)
 {
   librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
index b423052a40d700da8389a1db8ff5bc2077524718..d6838c959598643bbc3b6f06c86cc9ddafc7d975 100644 (file)
@@ -96,6 +96,13 @@ public:
    */
   virtual int delete_bucket(std::string& id, std::string& bucket) = 0;
 
+  virtual int disable_bucket(std::string& bucket) { return -ENOTSUP; }
+  virtual int enable_bucket(std::string& bucket, uint64_t auid) { return -ENOTSUP; }
+  virtual int bucket_suspended(std::string& bucket, bool *suspended) {
+    *suspended = false;
+    return 0;
+  }
+
   /**
    * Delete an object.
    * id: unused in current implementations
index 42af27b607186446085801df780e6c41898e7801..3fc07a6277a4734e26328627cc495fd54e305e2c 100644 (file)
@@ -34,6 +34,8 @@ void usage()
   cerr << "  user modify                modify user\n";
   cerr << "  user info                  get user info\n";
   cerr << "  user rm                    remove user\n";
+  cerr << "  user suspend               suspend a user\n";
+  cerr << "  user enable                reenable user after suspension\n";
   cerr << "  subuser create             create a new subuser\n" ;
   cerr << "  subuser modify             modify subuser\n";
   cerr << "  subuser rm                 remove subuser\n";
@@ -77,6 +79,8 @@ enum {
   OPT_USER_INFO,
   OPT_USER_MODIFY,
   OPT_USER_RM,
+  OPT_USER_SUSPEND,
+  OPT_USER_ENABLE,
   OPT_SUBUSER_CREATE,
   OPT_SUBUSER_MODIFY,
   OPT_SUBUSER_RM,
@@ -177,6 +181,10 @@ static int get_cmd(const char *cmd, const char *prev_cmd, bool *need_more)
       return OPT_USER_MODIFY;
     if (strcmp(cmd, "rm") == 0)
       return OPT_USER_RM;
+    if (strcmp(cmd, "suspend") == 0)
+      return OPT_USER_SUSPEND;
+    if (strcmp(cmd, "enable") == 0)
+      return OPT_USER_ENABLE;
   } else if (strcmp(prev_cmd, "subuser") == 0) {
     if (strcmp(cmd, "create") == 0)
       return OPT_SUBUSER_CREATE;
@@ -331,6 +339,7 @@ static void remove_old_indexes(RGWUserInfo& old_info, RGWUserInfo new_info)
     cerr << "ERROR: this should be fixed manually!" << std::endl;
 }
 
+
 int main(int argc, char **argv) 
 {
   DEFINE_CONF_VARS(usage);
@@ -506,7 +515,8 @@ int main(int argc, char **argv)
 
 
   if (user_modify_op || opt_cmd == OPT_USER_CREATE ||
-      opt_cmd == OPT_USER_INFO || opt_cmd == OPT_BUCKET_UNLINK || opt_cmd == OPT_BUCKET_LINK) {
+      opt_cmd == OPT_USER_INFO || opt_cmd == OPT_BUCKET_UNLINK || opt_cmd == OPT_BUCKET_LINK ||
+      opt_cmd == OPT_USER_SUSPEND || opt_cmd == OPT_USER_ENABLE) {
     if (!user_id) {
       cerr << "user_id was not specified, aborting" << std::endl;
       usage();
@@ -901,5 +911,50 @@ int main(int argc, char **argv)
     }
   }
 
+ if (opt_cmd == OPT_USER_SUSPEND || opt_cmd == OPT_USER_ENABLE) {
+    string id;
+    __u8 disable = (opt_cmd == OPT_USER_SUSPEND ? 1 : 0);
+
+    if (!user_id) {
+      cerr << "uid was not specified" << std::endl;
+      usage();
+    }
+    RGWUserBuckets buckets;
+    if (rgw_read_user_buckets(user_id, buckets, false) < 0) {
+      cout << "could not get buckets for uid " << user_id << std::endl;
+    }
+    map<string, RGWBucketEnt>& m = buckets.get_buckets();
+    map<string, RGWBucketEnt>::iterator iter;
+
+    int ret;
+    info.suspended = disable;
+    ret = rgw_store_user_info(info);
+    if (ret < 0) {
+      cerr << "ERROR: failed to store user info user=" << user_id << " ret=" << ret << std::endl;
+      exit(1);
+    }
+     
+    if (disable)
+      RGW_LOG(0) << "disabling user buckets" << dendl;
+    else
+      RGW_LOG(0) << "enabling user buckets" << dendl;
+
+    bool fail = false;
+
+    for (iter = m.begin(); iter != m.end(); ++iter) {
+      RGWBucketEnt obj = iter->second;
+      if (disable)
+        ret = rgwstore->disable_bucket(obj.name);
+      else
+        ret = rgwstore->enable_bucket(obj.name, info.auid);
+      if (ret < 0) {
+        cerr << "ERROR: could not disable bucket " << obj.name << " ret=" << ret << std::endl;
+        fail = true;
+      }
+    }
+    if (fail)
+      return 1;
+  } 
+
   return 0;
 }
index c5c0b895b924e2d630c1aa2d767fddb51f741063..d9a9d2b035cb47c0f6854b68412a6fad24954a63 100644 (file)
@@ -44,7 +44,7 @@ extern string rgw_root_bucket;
 
 #define RGW_BUCKETS_OBJ_PREFIX ".buckets"
 
-#define USER_INFO_VER 6
+#define USER_INFO_VER 7
 
 #define RGW_MAX_CHUNK_SIZE     (4*1024*1024)
 
@@ -57,6 +57,8 @@ extern string rgw_root_bucket;
 #define RGW_REST_OPENSTACK      0x1
 #define RGW_REST_OPENSTACK_AUTH 0x2
 
+#define RGW_SUSPENDED_USER_AUID -2
+
 #define CGI_PRINTF(state, format, ...) do { \
    int __ret = FCGX_FPrintF(state->fcgx->out, format, __VA_ARGS__); \
    if (state->header_ended) \
@@ -86,6 +88,8 @@ extern string rgw_root_bucket;
 #define ERR_INVALID_PART_ORDER  2008
 #define ERR_NO_SUCH_UPLOAD      2009
 
+#define ERR_USER_SUSPENDED      2100
+
 typedef void *RGWAccessHandle;
 
  /* size should be the required string size + 1 */
@@ -221,6 +225,7 @@ struct RGWUserInfo
   string openstack_key;
   map<string, RGWAccessKey> access_keys;
   map<string, RGWSubUser> subusers;
+  __u8 suspended;
 
   RGWUserInfo() : auid(0) {}
 
@@ -245,6 +250,7 @@ struct RGWUserInfo
      ::encode(user_id, bl);
      ::encode(access_keys, bl);
      ::encode(subusers, bl);
+     ::encode(suspended, bl);
   }
   void decode(bufferlist::iterator& bl) {
      __u32 ver;
@@ -273,6 +279,10 @@ struct RGWUserInfo
       ::decode(access_keys, bl);
       ::decode(subusers, bl);
     }
+    suspended = 0;
+    if (ver >= 7) {
+      ::decode(suspended, bl);
+    }
   }
 
   void clear() {
@@ -281,6 +291,7 @@ struct RGWUserInfo
     user_email.clear();
     auid = CEPH_AUTH_UID_DEFAULT;
     access_keys.clear();
+    suspended = 0;
   }
 };
 WRITE_CLASS_ENCODER(RGWUserInfo)
index 559016b7eb13d47d77b3edbf8c232a9246565ea9..f80997921bc034c23377da4b78f0904fc6b69c3a 100644 (file)
@@ -102,6 +102,11 @@ int main(int argc, const char **argv)
       abort_early(&s, -EPERM);
       goto done;
     }
+    if (s.user.suspended) {
+      RGW_LOG(10) << "user is suspended, uid=" << s.user.user_id << dendl;
+      abort_early(&s, -ERR_USER_SUSPENDED);
+      goto done;
+    }
     ret = handler->read_permissions();
     if (ret < 0) {
       abort_early(&s, ret);
index 4b6329ebd90d8fcb6d07a817b2fee1e5ad65aecd..40d648924aa39446f14a2b7489fe34e867ca70a2 100644 (file)
@@ -138,6 +138,15 @@ int read_acls(struct req_state *s, RGWAccessControlPolicy *policy, string& bucke
   string oid = object;
   rgw_obj obj;
 
+  if (!oid.empty()) {
+    bool suspended;
+    int ret = rgwstore->bucket_suspended(bucket, &suspended);
+    if (ret < 0)
+      return ret;
+    if (suspended)
+      return -ERR_USER_SUSPENDED;
+  }
+
   if (!oid.empty() && !upload_id.empty()) {
     RGWMPObj mp(oid, upload_id);
     oid = mp.get_meta();
index d8fd41272b480fd02e70687e8656f0f3dcd777f0..3fe68e367fc5921bd15e0411eae4c179aa21a498 100644 (file)
@@ -486,6 +486,44 @@ int RGWRados::delete_bucket(std::string& id, std::string& bucket)
   return 0;
 }
 
+int RGWRados::disable_bucket(std::string& bucket)
+{
+  librados::IoCtx ctx;
+  int r = open_bucket_ctx(bucket, ctx);
+  if (r < 0)
+    return r;
+
+  ctx.set_auid(RGW_SUSPENDED_USER_AUID);
+
+  return 0;
+}
+
+int RGWRados::enable_bucket(std::string& bucket, uint64_t auid)
+{
+  librados::IoCtx ctx;
+  int r = open_bucket_ctx(bucket, ctx);
+  if (r < 0)
+    return r;
+
+  ctx.set_auid(auid);
+  return 0;
+}
+
+int RGWRados::bucket_suspended(std::string& bucket, bool *suspended)
+{
+  librados::IoCtx ctx;
+  int r = open_bucket_ctx(bucket, ctx);
+  if (r < 0)
+    return r;
+
+  uint64_t auid;
+  int ret = ctx.get_auid(&auid);
+  if (ret < 0)
+    return ret;
+
+  *suspended = (auid == RGW_SUSPENDED_USER_AUID);
+  return 0;
+}
 /**
  * Delete an object.
  * id: unused
index 07070d7a91a6e3c7d1ab9bb20fddc4203f4634a6..89f6a4937379cba92964fe851ed980d35fda8879 100644 (file)
@@ -61,6 +61,10 @@ public:
   /** delete a bucket*/
   virtual int delete_bucket(std::string& id, std::string& bucket);
 
+  virtual int disable_bucket(std::string& bucket);
+  virtual int enable_bucket(std::string& bucket, uint64_t auid);
+  virtual int bucket_suspended(std::string& bucket, bool *suspended);
+
   /** Delete an object.*/
   virtual int delete_obj(std::string& id, rgw_obj& src_obj);
 
index 99926dc7c8f300ccc60c8f0b6128488ea10d117a..0288dac001a6929532967f0026584eba1d2ad6b7 100644 (file)
@@ -48,6 +48,7 @@ const static struct rgw_html_errors RGW_HTML_ERRORS[] = {
     { ERR_INVALID_PART_ORDER, 400, "InvalidPartOrder" },
     { EACCES, 403, "AccessDenied" },
     { EPERM, 403, "AccessDenied" },
+    { ERR_USER_SUSPENDED, 403, "UserSuspended" },
     { ENOENT, 404, "NoSuchKey" },
     { ERR_NO_SUCH_BUCKET, 404, "NoSuchBucket" },
     { ERR_NO_SUCH_UPLOAD, 404, "NoSuchUpload" },