You can add read, write or all capabilities to users, buckets, metadata and
usage (utilization). For example::
- --caps="[users|buckets|metadata|usage|zone|amz-cache|info|bilog|mdlog|datalog|user-policy|oidc-provider|roles|ratelimit]=[*|read|write|read, write]"
+ --caps="[users|buckets|metadata|usage|zone|amz-cache|info|bilog|mdlog|datalog|user-policy|oidc-provider|roles|ratelimit|users-without-keys]=[*|read|write|read, write]"
For example::
Get User Info
=============
-Get user information.
+Get user information. Cap ``users`` must be set to ``read`` to run this operation.
+If additional cap ``users-without-keys`` is set to ``read`` or ``*``, S3 Key and Swift keys will not be
+included in the response unless the user running this operation is the system user.
:caps: users=read
-
+:optional cap: users-without-keys=read
Syntax
~~~~~~
``keys``
:Description: S3 keys associated with this user account.
+ If the optional cap ``users-without-keys`` is set to ``read``, S3 keys are not in the response.
:Type: Container
:Parent: ``user``
``swift_keys``
:Description: Swift keys associated with this user account.
+ If the optional cap ``users-without-keys`` is set to ``read``, Swift keys are not in the response.
:Type: Container
:Parent: ``user``
assert out['type'] == 'rgw'
assert out['mfa_ids'] == []
+ # TESTCASE 'info-existing','user','info','existing user','returns no keys with users-without-keys cap set to read'
+ (err, out) = rgwadmin(ctx, client, [
+ 'caps', 'add',
+ '--uid', admin_user,
+ '--caps', 'users-without-keys=read'
+ ])
+ logging.error(out)
+ logging.error(err)
+ assert not err
+
+ (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' : user1})
+ assert 'keys' in out
+ assert 'swift_keys' in out
+
+ # TESTCASE 'info-existing','user','info','existing user','returns no keys with users-without-keys cap set to read'
+ (err, out) = rgwadmin(ctx, client, [
+ 'caps', 'add',
+ '--uid', admin_user,
+ '--caps', 'users-without-keys=*'
+ ])
+ logging.error(out)
+ logging.error(err)
+ assert not err
+
+ (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' : user1})
+ assert 'keys' in out
+ assert 'swift_keys' in out
+
+ # TESTCASE 'info-existing','user','info','existing user','returns keys with users-without-keys cap set to write'
+ (err, out) = rgwadmin(ctx, client, [
+ 'caps', 'rm',
+ '--uid', admin_user,
+ '--caps', 'users-without-keys=*'
+ ])
+ logging.error(out)
+ logging.error(err)
+ assert not err
+
+ (err, out) = rgwadmin(ctx, client, [
+ 'caps', 'add',
+ '--uid', admin_user,
+ '--caps', 'users-without-keys=write'
+ ])
+ logging.error(out)
+ logging.error(err)
+ assert not err
+
+ (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' : user1})
+ assert len(out['keys']) == 1
+ assert out['swift_keys'] == []
+
+ # remove cap users-without-keys permenantly for future testing
+ (err, out) = rgwadmin(ctx, client, [
+ 'caps', 'rm',
+ '--uid', admin_user,
+ '--caps', 'users-without-keys=write'
+ ])
+ logging.error(out)
+ logging.error(err)
+ assert not err
+
# TESTCASE 'suspend-ok','user','suspend','active user','succeeds'
(ret, out) = rgwadmin_rest(admin_conn, ['user', 'modify'], {'uid' : user1, 'suspended' : True})
assert ret == 200
# TESTCASE 'ratelimit' 'global' 'modify' 'anonymous' 'enabled' 'succeeds'
(ret, out) = rgwadmin_rest(admin_conn, ['ratelimit', 'modify'], {'ratelimit-scope' : 'bucket', 'global': 'true', 'enabled' : 'true'})
- assert ret == 200
\ No newline at end of file
+ assert ret == 200
void RGWOp_User_Info::execute(optional_yield y)
{
RGWUserAdminOpState op_state(driver);
+ op_state.set_system(s->system_request);
std::string uid_str, access_key_str;
bool fetch_stats;
bool sync_stats;
+ bool dump_keys = true;
RESTArgs::get_string(s, "uid", uid_str, &uid_str);
RESTArgs::get_string(s, "access-key", access_key_str, &access_key_str);
op_state.set_fetch_stats(fetch_stats);
op_state.set_sync_stats(sync_stats);
- op_ret = RGWUserAdminOp_User::info(s, driver, op_state, flusher, y);
+ // dump_keys is false if users-without-keys is 'read' and
+ // the user is not the system user
+ int keys_perm = s->user->get_info().caps.check_cap("users-without-keys", RGW_CAP_READ);
+ if (keys_perm == 0 && !op_state.system) {
+ dump_keys = false;
+ }
+
+ op_ret = RGWUserAdminOp_User::info(s, driver, op_state, flusher, dump_keys, y);
}
class RGWOp_User_Create : public RGWRESTOp {
f->close_section();
}
-static void dump_user_info(Formatter *f, RGWUserInfo &info,
- RGWStorageStats *stats = NULL)
+static void dump_user_info(const DoutPrefixProvider* dpp, Formatter *f, RGWUserInfo &info,
+ bool dump_keys, RGWStorageStats *stats = NULL)
{
f->open_object_section("user_info");
encode_json("tenant", info.user_id.tenant, f);
encode_json("max_buckets", (int)info.max_buckets, f);
dump_subusers_info(f, info);
- dump_access_keys_info(f, info);
- dump_swift_keys_info(f, info);
+
+ if (dump_keys) {
+ dump_access_keys_info(f, info);
+ dump_swift_keys_info(f, info);
+ }
encode_json("caps", info.caps, f);
int RGWUserAdminOp_User::info(const DoutPrefixProvider *dpp,
rgw::sal::Driver* driver, RGWUserAdminOpState& op_state,
RGWFormatterFlusher& flusher,
+ bool dump_keys,
optional_yield y)
{
RGWUserInfo info;
if (formatter) {
flusher.start(0);
- dump_user_info(formatter, info, arg_stats);
+ dump_user_info(dpp, formatter, info, dump_keys, arg_stats);
flusher.flush();
}
if (formatter) {
flusher.start(0);
- dump_user_info(formatter, info);
+ dump_user_info(dpp, formatter, info, true);
flusher.flush();
}
if (formatter) {
flusher.start(0);
- dump_user_info(formatter, info);
+ dump_user_info(dpp, formatter, info, true);
flusher.flush();
}
static int info(const DoutPrefixProvider *dpp,
rgw::sal::Driver* driver,
RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher,
- optional_yield y);
+ bool dump_keys, optional_yield y);
static int create(const DoutPrefixProvider *dpp,
rgw::sal::Driver* driver,
"user-policy",
"amz-cache",
"oidc-provider",
+ "users-without-keys",
"ratelimit"};
for (unsigned int i = 0; i < sizeof(cap_type) / sizeof(char *); ++i) {